diff options
Diffstat (limited to 'drivers/media/platform/s5p-tv/hdmiphy_drv.c')
-rw-r--r-- | drivers/media/platform/s5p-tv/hdmiphy_drv.c | 55 |
1 files changed, 22 insertions, 33 deletions
diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c index 80717cec76ae..e19a0af1ea4f 100644 --- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c | |||
@@ -176,35 +176,9 @@ static inline struct hdmiphy_ctx *sd_to_ctx(struct v4l2_subdev *sd) | |||
176 | return container_of(sd, struct hdmiphy_ctx, sd); | 176 | return container_of(sd, struct hdmiphy_ctx, sd); |
177 | } | 177 | } |
178 | 178 | ||
179 | static unsigned long hdmiphy_preset_to_pixclk(u32 preset) | 179 | static const u8 *hdmiphy_find_conf(unsigned long pixclk, |
180 | const struct hdmiphy_conf *conf) | ||
180 | { | 181 | { |
181 | static const unsigned long pixclk[] = { | ||
182 | [V4L2_DV_480P59_94] = 27000000, | ||
183 | [V4L2_DV_576P50] = 27000000, | ||
184 | [V4L2_DV_720P59_94] = 74176000, | ||
185 | [V4L2_DV_720P50] = 74250000, | ||
186 | [V4L2_DV_720P60] = 74250000, | ||
187 | [V4L2_DV_1080P24] = 74250000, | ||
188 | [V4L2_DV_1080P30] = 74250000, | ||
189 | [V4L2_DV_1080I50] = 74250000, | ||
190 | [V4L2_DV_1080I60] = 74250000, | ||
191 | [V4L2_DV_1080P50] = 148500000, | ||
192 | [V4L2_DV_1080P60] = 148500000, | ||
193 | }; | ||
194 | if (preset < ARRAY_SIZE(pixclk)) | ||
195 | return pixclk[preset]; | ||
196 | else | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static const u8 *hdmiphy_find_conf(u32 preset, const struct hdmiphy_conf *conf) | ||
201 | { | ||
202 | unsigned long pixclk; | ||
203 | |||
204 | pixclk = hdmiphy_preset_to_pixclk(preset); | ||
205 | if (!pixclk) | ||
206 | return NULL; | ||
207 | |||
208 | for (; conf->pixclk; ++conf) | 182 | for (; conf->pixclk; ++conf) |
209 | if (conf->pixclk == pixclk) | 183 | if (conf->pixclk == pixclk) |
210 | return conf->data; | 184 | return conf->data; |
@@ -217,8 +191,8 @@ static int hdmiphy_s_power(struct v4l2_subdev *sd, int on) | |||
217 | return 0; | 191 | return 0; |
218 | } | 192 | } |
219 | 193 | ||
220 | static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd, | 194 | static int hdmiphy_s_dv_timings(struct v4l2_subdev *sd, |
221 | struct v4l2_dv_preset *preset) | 195 | struct v4l2_dv_timings *timings) |
222 | { | 196 | { |
223 | const u8 *data; | 197 | const u8 *data; |
224 | u8 buffer[32]; | 198 | u8 buffer[32]; |
@@ -226,9 +200,12 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd, | |||
226 | struct hdmiphy_ctx *ctx = sd_to_ctx(sd); | 200 | struct hdmiphy_ctx *ctx = sd_to_ctx(sd); |
227 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 201 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
228 | struct device *dev = &client->dev; | 202 | struct device *dev = &client->dev; |
203 | unsigned long pixclk = timings->bt.pixelclock; | ||
229 | 204 | ||
230 | dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset); | 205 | dev_info(dev, "s_dv_timings\n"); |
231 | data = hdmiphy_find_conf(preset->preset, ctx->conf_tab); | 206 | if ((timings->bt.flags & V4L2_DV_FL_REDUCED_FPS) && pixclk == 74250000) |
207 | pixclk = 74176000; | ||
208 | data = hdmiphy_find_conf(pixclk, ctx->conf_tab); | ||
232 | if (!data) { | 209 | if (!data) { |
233 | dev_err(dev, "format not supported\n"); | 210 | dev_err(dev, "format not supported\n"); |
234 | return -EINVAL; | 211 | return -EINVAL; |
@@ -245,6 +222,17 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd, | |||
245 | return 0; | 222 | return 0; |
246 | } | 223 | } |
247 | 224 | ||
225 | static int hdmiphy_dv_timings_cap(struct v4l2_subdev *sd, | ||
226 | struct v4l2_dv_timings_cap *cap) | ||
227 | { | ||
228 | cap->type = V4L2_DV_BT_656_1120; | ||
229 | /* The phy only determines the pixelclock, leave the other values | ||
230 | * at 0 to signify that we have no information for them. */ | ||
231 | cap->bt.min_pixelclock = 27000000; | ||
232 | cap->bt.max_pixelclock = 148500000; | ||
233 | return 0; | ||
234 | } | ||
235 | |||
248 | static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable) | 236 | static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable) |
249 | { | 237 | { |
250 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 238 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
@@ -270,7 +258,8 @@ static const struct v4l2_subdev_core_ops hdmiphy_core_ops = { | |||
270 | }; | 258 | }; |
271 | 259 | ||
272 | static const struct v4l2_subdev_video_ops hdmiphy_video_ops = { | 260 | static const struct v4l2_subdev_video_ops hdmiphy_video_ops = { |
273 | .s_dv_preset = hdmiphy_s_dv_preset, | 261 | .s_dv_timings = hdmiphy_s_dv_timings, |
262 | .dv_timings_cap = hdmiphy_dv_timings_cap, | ||
274 | .s_stream = hdmiphy_s_stream, | 263 | .s_stream = hdmiphy_s_stream, |
275 | }; | 264 | }; |
276 | 265 | ||