Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.infradead.org/users/kmpar…
Browse files Browse the repository at this point in the history
…k/linux-samsung into drm-next

Inki writes:
"this patch set updates exynos drm framework and includes minor fixups.
and this pull request except hdmi device tree support patch set posted
by Rahul Sharma because that includes media side patch so for this
patch set, we may have git pull one more time in addition, if we get
an agreement with media guys. for this patch, you can refer to below link,
        http://comments.gmane.org/gmane.comp.video.dri.devel/74504

 this pull request adds hdmi device tree support
and includes related patch set such as disabling of hdmi internal
interrupt, suppport for platform variants for hdmi and mixer,
support to disable video processor based on platform type and
removal of drm common platform data. as you know, this patch
set was delayed because it included an media side patch. so for this,
we got an ack from v4l2-based hdmi driver author, Tomasz Stanislawski."

* 'exynos-drm-next' of git://git.infradead.org/users/kmpark/linux-samsung: (34 commits)
  drm: exynos: hdmi: remove drm common hdmi platform data struct
  drm: exynos: hdmi: add support for exynos5 hdmi
  drm: exynos: hdmi: replace is_v13 with version check in hdmi
  drm: exynos: hdmi: add support for exynos5 mixer
  drm: exynos: hdmi: add support to disable video processor in mixer
  drm: exynos: hdmi: add support for platform variants for mixer
  drm: exynos: hdmi: add support for exynos5 hdmiphy
  drm: exynos: hdmi: add support for exynos5 ddc
  drm: exynos: remove drm hdmi platform data struct
  drm: exynos: hdmi: turn off HPD interrupt in HDMI chip
  drm: exynos: hdmi: use s5p-hdmi platform data
  drm: exynos: hdmi: fix interrupt handling
  drm: exynos: hdmi: support for platform variants
  media: s5p-hdmi: add HPD GPIO to platform data
  drm/exynos: fix kcalloc size of g2d cmdlist node
  drm/exynos: fix to calculate CRTC shown via screen
  drm/exynos: fix display power call issue.
  drm/exynos: add platform_device_id table and driver data for drm fimd
  drm/exynos: Fix potential NULL pointer dereference
  drm/exynos: support drm_wait_vblank feature for VIDI
  ...

Conflicts:
	include/drm/exynos_drm.h
  • Loading branch information
Dave Airlie committed Oct 7, 2012
2 parents 0dbe232 + 768c305 commit a5a0fc6
Show file tree
Hide file tree
Showing 22 changed files with 898 additions and 244 deletions.
22 changes: 17 additions & 5 deletions drivers/gpu/drm/exynos/exynos_ddc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,41 @@ static int s5p_ddc_probe(struct i2c_client *client,
{
hdmi_attach_ddc_client(client);

dev_info(&client->adapter->dev, "attached s5p_ddc "
"into i2c adapter successfully\n");
dev_info(&client->adapter->dev,
"attached %s into i2c adapter successfully\n",
client->name);

return 0;
}

static int s5p_ddc_remove(struct i2c_client *client)
{
dev_info(&client->adapter->dev, "detached s5p_ddc "
"from i2c adapter successfully\n");
dev_info(&client->adapter->dev,
"detached %s from i2c adapter successfully\n",
client->name);

return 0;
}

static struct i2c_device_id ddc_idtable[] = {
{"s5p_ddc", 0},
{"exynos5-hdmiddc", 0},
{ },
};

static struct of_device_id hdmiddc_match_types[] = {
{
.compatible = "samsung,exynos5-hdmiddc",
}, {
/* end node */
}
};

struct i2c_driver ddc_driver = {
.driver = {
.name = "s5p_ddc",
.name = "exynos-hdmiddc",
.owner = THIS_MODULE,
.of_match_table = hdmiddc_match_types,
},
.id_table = ddc_idtable,
.probe = s5p_ddc_probe,
Expand Down
50 changes: 46 additions & 4 deletions drivers/gpu/drm/exynos/exynos_drm_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct exynos_drm_connector {
struct drm_connector drm_connector;
uint32_t encoder_id;
struct exynos_drm_manager *manager;
uint32_t dpms;
};

/* convert exynos_video_timings to drm_display_mode */
Expand Down Expand Up @@ -149,8 +150,12 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
count = drm_add_edid_modes(connector, edid);
kfree(edid);
} else {
struct drm_display_mode *mode = drm_mode_create(connector->dev);
struct exynos_drm_panel_info *panel;
struct drm_display_mode *mode = drm_mode_create(connector->dev);
if (!mode) {
DRM_ERROR("failed to create a new display mode.\n");
return 0;
}

if (display_ops->get_panel)
panel = display_ops->get_panel(manager->dev);
Expand Down Expand Up @@ -194,8 +199,7 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
return ret;
}

static struct drm_encoder *exynos_drm_best_encoder(
struct drm_connector *connector)
struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct exynos_drm_connector *exynos_connector =
Expand Down Expand Up @@ -224,6 +228,43 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
.best_encoder = exynos_drm_best_encoder,
};

void exynos_drm_display_power(struct drm_connector *connector, int mode)
{
struct drm_encoder *encoder = exynos_drm_best_encoder(connector);
struct exynos_drm_connector *exynos_connector;
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
struct exynos_drm_display_ops *display_ops = manager->display_ops;

exynos_connector = to_exynos_connector(connector);

if (exynos_connector->dpms == mode) {
DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
return;
}

if (display_ops && display_ops->power_on)
display_ops->power_on(manager->dev, mode);

exynos_connector->dpms = mode;
}

static void exynos_drm_connector_dpms(struct drm_connector *connector,
int mode)
{
DRM_DEBUG_KMS("%s\n", __FILE__);

/*
* in case that drm_crtc_helper_set_mode() is called,
* encoder/crtc->funcs->dpms() will be just returned
* because they already were DRM_MODE_DPMS_ON so only
* exynos_drm_display_power() will be called.
*/
drm_helper_connector_dpms(connector, mode);

exynos_drm_display_power(connector, mode);

}

static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
unsigned int max_width, unsigned int max_height)
{
Expand Down Expand Up @@ -283,7 +324,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
}

static struct drm_connector_funcs exynos_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.dpms = exynos_drm_connector_dpms,
.fill_modes = exynos_drm_connector_fill_modes,
.detect = exynos_drm_connector_detect,
.destroy = exynos_drm_connector_destroy,
Expand Down Expand Up @@ -332,6 +373,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,

exynos_connector->encoder_id = encoder->base.id;
exynos_connector->manager = manager;
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
connector->encoder = encoder;

err = drm_mode_connector_attach_encoder(connector, encoder);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@
struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
struct drm_encoder *encoder);

struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector);

void exynos_drm_display_power(struct drm_connector *connector, int mode);

#endif
100 changes: 69 additions & 31 deletions drivers/gpu/drm/exynos/exynos_drm_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,15 @@

static LIST_HEAD(exynos_drm_subdrv_list);

static int exynos_drm_subdrv_probe(struct drm_device *dev,
static int exynos_drm_create_enc_conn(struct drm_device *dev,
struct exynos_drm_subdrv *subdrv)
{
struct drm_encoder *encoder;
struct drm_connector *connector;
int ret;

DRM_DEBUG_DRIVER("%s\n", __FILE__);

if (subdrv->probe) {
int ret;

/*
* this probe callback would be called by sub driver
* after setting of all resources to this sub driver,
* such as clock, irq and register map are done or by load()
* of exynos drm driver.
*
* P.S. note that this driver is considered for modularization.
*/
ret = subdrv->probe(dev, subdrv->dev);
if (ret)
return ret;
}

if (!subdrv->manager)
return 0;

subdrv->manager->dev = subdrv->dev;

/* create and initialize a encoder for this sub driver. */
Expand All @@ -78,24 +60,22 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
connector = exynos_drm_connector_create(dev, encoder);
if (!connector) {
DRM_ERROR("failed to create connector\n");
encoder->funcs->destroy(encoder);
return -EFAULT;
ret = -EFAULT;
goto err_destroy_encoder;
}

subdrv->encoder = encoder;
subdrv->connector = connector;

return 0;

err_destroy_encoder:
encoder->funcs->destroy(encoder);
return ret;
}

static void exynos_drm_subdrv_remove(struct drm_device *dev,
struct exynos_drm_subdrv *subdrv)
static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
{
DRM_DEBUG_DRIVER("%s\n", __FILE__);

if (subdrv->remove)
subdrv->remove(dev);

if (subdrv->encoder) {
struct drm_encoder *encoder = subdrv->encoder;
encoder->funcs->destroy(encoder);
Expand All @@ -109,9 +89,43 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
}
}

static int exynos_drm_subdrv_probe(struct drm_device *dev,
struct exynos_drm_subdrv *subdrv)
{
if (subdrv->probe) {
int ret;

subdrv->drm_dev = dev;

/*
* this probe callback would be called by sub driver
* after setting of all resources to this sub driver,
* such as clock, irq and register map are done or by load()
* of exynos drm driver.
*
* P.S. note that this driver is considered for modularization.
*/
ret = subdrv->probe(dev, subdrv->dev);
if (ret)
return ret;
}

return 0;
}

static void exynos_drm_subdrv_remove(struct drm_device *dev,
struct exynos_drm_subdrv *subdrv)
{
DRM_DEBUG_DRIVER("%s\n", __FILE__);

if (subdrv->remove)
subdrv->remove(dev, subdrv->dev);
}

int exynos_drm_device_register(struct drm_device *dev)
{
struct exynos_drm_subdrv *subdrv, *n;
unsigned int fine_cnt = 0;
int err;

DRM_DEBUG_DRIVER("%s\n", __FILE__);
Expand All @@ -120,14 +134,36 @@ int exynos_drm_device_register(struct drm_device *dev)
return -EINVAL;

list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
subdrv->drm_dev = dev;
err = exynos_drm_subdrv_probe(dev, subdrv);
if (err) {
DRM_DEBUG("exynos drm subdrv probe failed.\n");
list_del(&subdrv->list);
continue;
}

/*
* if manager is null then it means that this sub driver
* doesn't need encoder and connector.
*/
if (!subdrv->manager) {
fine_cnt++;
continue;
}

err = exynos_drm_create_enc_conn(dev, subdrv);
if (err) {
DRM_DEBUG("failed to create encoder and connector.\n");
exynos_drm_subdrv_remove(dev, subdrv);
list_del(&subdrv->list);
continue;
}

fine_cnt++;
}

if (!fine_cnt)
return -EINVAL;

return 0;
}
EXPORT_SYMBOL_GPL(exynos_drm_device_register);
Expand All @@ -143,8 +179,10 @@ int exynos_drm_device_unregister(struct drm_device *dev)
return -EINVAL;
}

list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list)
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
exynos_drm_subdrv_remove(dev, subdrv);
exynos_drm_destroy_enc_conn(subdrv);
}

return 0;
}
Expand Down
20 changes: 13 additions & 7 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ struct exynos_drm_crtc {

static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);

DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
Expand All @@ -76,12 +75,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
return;
}

mutex_lock(&dev->struct_mutex);

exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms);
exynos_crtc->dpms = mode;

mutex_unlock(&dev->struct_mutex);
}

static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
Expand All @@ -97,6 +92,7 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)

DRM_DEBUG_KMS("%s\n", __FILE__);

exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
exynos_plane_commit(exynos_crtc->plane);
exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
}
Expand Down Expand Up @@ -126,8 +122,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,

DRM_DEBUG_KMS("%s\n", __FILE__);

exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);

/*
* copy the mode data adjusted by mode_fixup() into crtc->mode
* so that hardware can be seet to proper mode.
Expand Down Expand Up @@ -161,6 +155,12 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,

DRM_DEBUG_KMS("%s\n", __FILE__);

/* when framebuffer changing is requested, crtc's dpms should be on */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
DRM_ERROR("failed framebuffer changing request.\n");
return -EPERM;
}

crtc_w = crtc->fb->width - x;
crtc_h = crtc->fb->height - y;

Expand Down Expand Up @@ -213,6 +213,12 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,

DRM_DEBUG_KMS("%s\n", __FILE__);

/* when the page flip is requested, crtc's dpms should be on */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
DRM_ERROR("failed page flip request.\n");
return -EINVAL;
}

mutex_lock(&dev->struct_mutex);

if (event) {
Expand Down
Loading

0 comments on commit a5a0fc6

Please sign in to comment.