diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-04 09:28:57 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-23 10:58:05 -0300 |
commit | 8cf2f7ad9749980a455d61b5664ccb553c12fd0e (patch) | |
tree | 5ac217917301fbbf20a7edfff61f949b60debe8c /drivers/media/platform | |
parent | 8b2c3da108b08751ac65911e1797ef9a5342c727 (diff) |
[media] s5p-tv: add dv_timings support for hdmiphy
This just adds dv_timings support without modifying existing dv_preset
support, although I had to refactor a little bit in order to share
hdmiphy_find_conf() between the preset and timings code.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Acked-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r-- | drivers/media/platform/s5p-tv/hdmiphy_drv.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c index 80717cec76ae..ef0d8122f3e9 100644 --- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c @@ -197,14 +197,9 @@ static unsigned long hdmiphy_preset_to_pixclk(u32 preset) return 0; } -static const u8 *hdmiphy_find_conf(u32 preset, const struct hdmiphy_conf *conf) +static const u8 *hdmiphy_find_conf(unsigned long pixclk, + const struct hdmiphy_conf *conf) { - unsigned long pixclk; - - pixclk = hdmiphy_preset_to_pixclk(preset); - if (!pixclk) - return NULL; - for (; conf->pixclk; ++conf) if (conf->pixclk == pixclk) return conf->data; @@ -220,15 +215,49 @@ static int hdmiphy_s_power(struct v4l2_subdev *sd, int on) static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd, struct v4l2_dv_preset *preset) { - const u8 *data; + const u8 *data = NULL; u8 buffer[32]; int ret; struct hdmiphy_ctx *ctx = sd_to_ctx(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned long pixclk; struct device *dev = &client->dev; dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset); - data = hdmiphy_find_conf(preset->preset, ctx->conf_tab); + + pixclk = hdmiphy_preset_to_pixclk(preset->preset); + data = hdmiphy_find_conf(pixclk, ctx->conf_tab); + if (!data) { + dev_err(dev, "format not supported\n"); + return -EINVAL; + } + + /* storing configuration to the device */ + memcpy(buffer, data, 32); + ret = i2c_master_send(client, buffer, 32); + if (ret != 32) { + dev_err(dev, "failed to configure HDMIPHY via I2C\n"); + return -EIO; + } + + return 0; +} + +static int hdmiphy_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + const u8 *data; + u8 buffer[32]; + int ret; + struct hdmiphy_ctx *ctx = sd_to_ctx(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct device *dev = &client->dev; + unsigned long pixclk = timings->bt.pixelclock; + + dev_info(dev, "s_dv_timings\n"); + if ((timings->bt.flags & V4L2_DV_FL_REDUCED_FPS) && pixclk == 74250000) + pixclk = 74176000; + data = hdmiphy_find_conf(pixclk, ctx->conf_tab); if (!data) { dev_err(dev, "format not supported\n"); return -EINVAL; @@ -245,6 +274,17 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd, return 0; } +static int hdmiphy_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + cap->type = V4L2_DV_BT_656_1120; + /* The phy only determines the pixelclock, leave the other values + * at 0 to signify that we have no information for them. */ + cap->bt.min_pixelclock = 27000000; + cap->bt.max_pixelclock = 148500000; + return 0; +} + static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -271,6 +311,8 @@ static const struct v4l2_subdev_core_ops hdmiphy_core_ops = { static const struct v4l2_subdev_video_ops hdmiphy_video_ops = { .s_dv_preset = hdmiphy_s_dv_preset, + .s_dv_timings = hdmiphy_s_dv_timings, + .dv_timings_cap = hdmiphy_dv_timings_cap, .s_stream = hdmiphy_s_stream, }; |