diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-06-18 07:21:44 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-07-04 04:17:58 -0400 |
commit | ab0aee9526988a5f254ce58b59dbcb6a2ae42fd6 (patch) | |
tree | b0ea21cd1188d4b76116dfdee4aa853da7908aa3 /drivers/video | |
parent | c9d2c799447c2f51866fb1e7e88eb5061d11ac43 (diff) |
OMAPDSS: HDMI4: add support to set infoframe & HDMI mode
Instead of using hardcoded AVI infoframe, and a custom HDMI/DVI mode
selection based in internal videomode tables, add support to set the
infoframe and HDMI/DVI mode.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi4.c | 53 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi4_core.c | 62 |
2 files changed, 41 insertions, 74 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c index 626aad2bef46..6a8550cf43e5 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4.c | |||
@@ -281,29 +281,11 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev, | |||
281 | static void hdmi_display_set_timing(struct omap_dss_device *dssdev, | 281 | static void hdmi_display_set_timing(struct omap_dss_device *dssdev, |
282 | struct omap_video_timings *timings) | 282 | struct omap_video_timings *timings) |
283 | { | 283 | { |
284 | struct hdmi_cm cm; | ||
285 | const struct hdmi_config *t; | ||
286 | |||
287 | mutex_lock(&hdmi.lock); | 284 | mutex_lock(&hdmi.lock); |
288 | 285 | ||
289 | cm = hdmi_get_code(timings); | 286 | hdmi.cfg.timings = *timings; |
290 | hdmi.cfg.cm = cm; | ||
291 | |||
292 | t = hdmi_get_timings(cm.mode, cm.code); | ||
293 | if (t != NULL) { | ||
294 | hdmi.cfg = *t; | ||
295 | |||
296 | dispc_set_tv_pclk(t->timings.pixelclock); | ||
297 | } else { | ||
298 | hdmi.cfg.timings = *timings; | ||
299 | hdmi.cfg.cm.code = 0; | ||
300 | hdmi.cfg.cm.mode = HDMI_DVI; | ||
301 | |||
302 | dispc_set_tv_pclk(timings->pixelclock); | ||
303 | } | ||
304 | 287 | ||
305 | DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ? | 288 | dispc_set_tv_pclk(timings->pixelclock); |
306 | "DVI" : "HDMI", hdmi.cfg.cm.code); | ||
307 | 289 | ||
308 | mutex_unlock(&hdmi.lock); | 290 | mutex_unlock(&hdmi.lock); |
309 | } | 291 | } |
@@ -311,14 +293,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev, | |||
311 | static void hdmi_display_get_timings(struct omap_dss_device *dssdev, | 293 | static void hdmi_display_get_timings(struct omap_dss_device *dssdev, |
312 | struct omap_video_timings *timings) | 294 | struct omap_video_timings *timings) |
313 | { | 295 | { |
314 | const struct hdmi_config *cfg; | 296 | *timings = hdmi.cfg.timings; |
315 | struct hdmi_cm cm = hdmi.cfg.cm; | ||
316 | |||
317 | cfg = hdmi_get_timings(cm.mode, cm.code); | ||
318 | if (cfg == NULL) | ||
319 | cfg = hdmi_default_timing(); | ||
320 | |||
321 | memcpy(timings, &cfg->timings, sizeof(cfg->timings)); | ||
322 | } | 297 | } |
323 | 298 | ||
324 | static void hdmi_dump_regs(struct seq_file *s) | 299 | static void hdmi_dump_regs(struct seq_file *s) |
@@ -516,7 +491,7 @@ static int hdmi_audio_enable(struct omap_dss_device *dssdev) | |||
516 | 491 | ||
517 | mutex_lock(&hdmi.lock); | 492 | mutex_lock(&hdmi.lock); |
518 | 493 | ||
519 | if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { | 494 | if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) { |
520 | r = -EPERM; | 495 | r = -EPERM; |
521 | goto err; | 496 | goto err; |
522 | } | 497 | } |
@@ -554,7 +529,7 @@ static bool hdmi_audio_supported(struct omap_dss_device *dssdev) | |||
554 | 529 | ||
555 | mutex_lock(&hdmi.lock); | 530 | mutex_lock(&hdmi.lock); |
556 | 531 | ||
557 | r = hdmi_mode_has_audio(hdmi.cfg.cm.mode); | 532 | r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode); |
558 | 533 | ||
559 | mutex_unlock(&hdmi.lock); | 534 | mutex_unlock(&hdmi.lock); |
560 | return r; | 535 | return r; |
@@ -568,7 +543,7 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev, | |||
568 | 543 | ||
569 | mutex_lock(&hdmi.lock); | 544 | mutex_lock(&hdmi.lock); |
570 | 545 | ||
571 | if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { | 546 | if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) { |
572 | r = -EPERM; | 547 | r = -EPERM; |
573 | goto err; | 548 | goto err; |
574 | } | 549 | } |
@@ -615,6 +590,20 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev, | |||
615 | } | 590 | } |
616 | #endif | 591 | #endif |
617 | 592 | ||
593 | static int hdmi_set_infoframe(struct omap_dss_device *dssdev, | ||
594 | const struct hdmi_avi_infoframe *avi) | ||
595 | { | ||
596 | hdmi.cfg.infoframe = *avi; | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev, | ||
601 | bool hdmi_mode) | ||
602 | { | ||
603 | hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI; | ||
604 | return 0; | ||
605 | } | ||
606 | |||
618 | static const struct omapdss_hdmi_ops hdmi_ops = { | 607 | static const struct omapdss_hdmi_ops hdmi_ops = { |
619 | .connect = hdmi_connect, | 608 | .connect = hdmi_connect, |
620 | .disconnect = hdmi_disconnect, | 609 | .disconnect = hdmi_disconnect, |
@@ -627,6 +616,8 @@ static const struct omapdss_hdmi_ops hdmi_ops = { | |||
627 | .get_timings = hdmi_display_get_timings, | 616 | .get_timings = hdmi_display_get_timings, |
628 | 617 | ||
629 | .read_edid = hdmi_read_edid, | 618 | .read_edid = hdmi_read_edid, |
619 | .set_infoframe = hdmi_set_infoframe, | ||
620 | .set_hdmi_mode = hdmi_set_hdmi_mode, | ||
630 | 621 | ||
631 | .audio_enable = hdmi_audio_enable, | 622 | .audio_enable = hdmi_audio_enable, |
632 | .audio_disable = hdmi_audio_disable, | 623 | .audio_disable = hdmi_audio_disable, |
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c index dbdbc5836d51..4ad39cfce254 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi4_core.c +++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c | |||
@@ -197,8 +197,7 @@ int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len) | |||
197 | return l; | 197 | return l; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | 200 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg) |
201 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
202 | { | 201 | { |
203 | DSSDBG("Enter hdmi_core_init\n"); | 202 | DSSDBG("Enter hdmi_core_init\n"); |
204 | 203 | ||
@@ -209,16 +208,6 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | |||
209 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | 208 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; |
210 | video_cfg->hdmi_dvi = HDMI_DVI; | 209 | video_cfg->hdmi_dvi = HDMI_DVI; |
211 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | 210 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; |
212 | |||
213 | /* packet enable and repeat */ | ||
214 | repeat_cfg->audio_pkt = 0; | ||
215 | repeat_cfg->audio_pkt_repeat = 0; | ||
216 | repeat_cfg->avi_infoframe = 0; | ||
217 | repeat_cfg->avi_infoframe_repeat = 0; | ||
218 | repeat_cfg->gen_cntrl_pkt = 0; | ||
219 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
220 | repeat_cfg->generic_pkt = 0; | ||
221 | repeat_cfg->generic_pkt_repeat = 0; | ||
222 | } | 211 | } |
223 | 212 | ||
224 | static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) | 213 | static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) |
@@ -283,15 +272,18 @@ static void hdmi_core_video_config(struct hdmi_core_data *core, | |||
283 | HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); | 272 | HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); |
284 | } | 273 | } |
285 | 274 | ||
286 | static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core) | 275 | static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core, |
276 | struct hdmi_avi_infoframe *frame) | ||
287 | { | 277 | { |
288 | void __iomem *av_base = hdmi_av_base(core); | 278 | void __iomem *av_base = hdmi_av_base(core); |
289 | struct hdmi_avi_infoframe *frame = &core->avi_infoframe; | ||
290 | u8 data[HDMI_INFOFRAME_SIZE(AVI)]; | 279 | u8 data[HDMI_INFOFRAME_SIZE(AVI)]; |
291 | int i; | 280 | int i; |
292 | 281 | ||
293 | hdmi_avi_infoframe_pack(frame, data, sizeof(data)); | 282 | hdmi_avi_infoframe_pack(frame, data, sizeof(data)); |
294 | 283 | ||
284 | print_hex_dump_debug("AVI: ", DUMP_PREFIX_NONE, 16, 1, data, | ||
285 | HDMI_INFOFRAME_SIZE(AVI), false); | ||
286 | |||
295 | for (i = 0; i < sizeof(data); ++i) { | 287 | for (i = 0; i < sizeof(data); ++i) { |
296 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_BASE + i * 4, | 288 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_BASE + i * 4, |
297 | data[i]); | 289 | data[i]); |
@@ -324,10 +316,9 @@ void hdmi4_configure(struct hdmi_core_data *core, | |||
324 | struct hdmi_video_format video_format; | 316 | struct hdmi_video_format video_format; |
325 | /* HDMI core */ | 317 | /* HDMI core */ |
326 | struct hdmi_core_video_config v_core_cfg; | 318 | struct hdmi_core_video_config v_core_cfg; |
327 | struct hdmi_core_packet_enable_repeat repeat_cfg; | 319 | struct hdmi_core_packet_enable_repeat repeat_cfg = { 0 }; |
328 | struct hdmi_avi_infoframe *avi_infoframe = &core->avi_infoframe; | ||
329 | 320 | ||
330 | hdmi_core_init(&v_core_cfg, &repeat_cfg); | 321 | hdmi_core_init(&v_core_cfg); |
331 | 322 | ||
332 | hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); | 323 | hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); |
333 | 324 | ||
@@ -350,39 +341,24 @@ void hdmi4_configure(struct hdmi_core_data *core, | |||
350 | hdmi_core_powerdown_disable(core); | 341 | hdmi_core_powerdown_disable(core); |
351 | 342 | ||
352 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | 343 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; |
353 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | 344 | v_core_cfg.hdmi_dvi = cfg->hdmi_dvi_mode; |
354 | 345 | ||
355 | hdmi_core_video_config(core, &v_core_cfg); | 346 | hdmi_core_video_config(core, &v_core_cfg); |
356 | 347 | ||
357 | /* release software reset in the core */ | 348 | /* release software reset in the core */ |
358 | hdmi_core_swreset_release(core); | 349 | hdmi_core_swreset_release(core); |
359 | 350 | ||
360 | /* | 351 | if (cfg->hdmi_dvi_mode == HDMI_HDMI) { |
361 | * configure packet | 352 | hdmi_core_write_avi_infoframe(core, &cfg->infoframe); |
362 | * info frame video see doc CEA861-D page 65 | 353 | |
363 | */ | 354 | /* enable/repeat the infoframe */ |
364 | hdmi_avi_infoframe_init(avi_infoframe); | 355 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; |
365 | avi_infoframe->colorspace = HDMI_COLORSPACE_RGB; | 356 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; |
366 | avi_infoframe->scan_mode = HDMI_SCAN_MODE_NONE; | 357 | /* wakeup */ |
367 | avi_infoframe->colorimetry = HDMI_COLORIMETRY_NONE; | 358 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; |
368 | avi_infoframe->picture_aspect = HDMI_PICTURE_ASPECT_NONE; | 359 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; |
369 | avi_infoframe->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE; | 360 | } |
370 | avi_infoframe->itc = 0; | ||
371 | avi_infoframe->extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; | ||
372 | avi_infoframe->quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; | ||
373 | avi_infoframe->nups = HDMI_NUPS_UNKNOWN; | ||
374 | avi_infoframe->video_code = cfg->cm.code; | ||
375 | avi_infoframe->ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; | ||
376 | avi_infoframe->content_type = HDMI_CONTENT_TYPE_NONE; | ||
377 | avi_infoframe->pixel_repeat = 0; | ||
378 | hdmi_core_aux_infoframe_avi_config(core); | ||
379 | 361 | ||
380 | /* enable/repeat the infoframe */ | ||
381 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
382 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
383 | /* wakeup */ | ||
384 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
385 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
386 | hdmi_core_av_packet_config(core, repeat_cfg); | 362 | hdmi_core_av_packet_config(core, repeat_cfg); |
387 | } | 363 | } |
388 | 364 | ||