| .. | .. |
|---|
| 45 | 45 | #include <media/videobuf2-v4l2.h> |
|---|
| 46 | 46 | #include <soc/rockchip/rockchip-system-status.h> |
|---|
| 47 | 47 | #include <sound/hdmi-codec.h> |
|---|
| 48 | +#include <linux/rk_hdmirx_class.h> |
|---|
| 48 | 49 | #include "rk_hdmirx.h" |
|---|
| 49 | 50 | #include "rk_hdmirx_cec.h" |
|---|
| 50 | 51 | #include "rk_hdmirx_hdcp.h" |
|---|
| 51 | 52 | |
|---|
| 52 | | -static struct class *hdmirx_class; |
|---|
| 53 | 53 | static int debug; |
|---|
| 54 | 54 | module_param(debug, int, 0644); |
|---|
| 55 | 55 | MODULE_PARM_DESC(debug, "debug level (0-3)"); |
|---|
| .. | .. |
|---|
| 269 | 269 | static void hdmirx_cancel_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev); |
|---|
| 270 | 270 | static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev); |
|---|
| 271 | 271 | static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev); |
|---|
| 272 | +static void hdmirx_interrupts_setup(struct rk_hdmirx_dev *hdmirx_dev, bool en); |
|---|
| 272 | 273 | |
|---|
| 273 | 274 | static u8 edid_init_data_340M[] = { |
|---|
| 274 | 275 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, |
|---|
| .. | .. |
|---|
| 529 | 530 | struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; |
|---|
| 530 | 531 | u32 dma_cfg1; |
|---|
| 531 | 532 | |
|---|
| 533 | + if (port_no_link(hdmirx_dev)) { |
|---|
| 534 | + v4l2_err(v4l2_dev, "%s port has no link!\n", __func__); |
|---|
| 535 | + return -ENOLINK; |
|---|
| 536 | + } |
|---|
| 537 | + |
|---|
| 538 | + if (signal_not_lock(hdmirx_dev)) { |
|---|
| 539 | + v4l2_err(v4l2_dev, "%s signal is not locked!\n", __func__); |
|---|
| 540 | + return -ENOLCK; |
|---|
| 541 | + } |
|---|
| 542 | + |
|---|
| 532 | 543 | *timings = hdmirx_dev->timings; |
|---|
| 533 | 544 | dma_cfg1 = hdmirx_readl(hdmirx_dev, DMA_CONFIG1); |
|---|
| 534 | 545 | v4l2_dbg(1, debug, v4l2_dev, "%s: pix_fmt: %s, DMA_CONFIG1:%#x\n", |
|---|
| .. | .. |
|---|
| 615 | 626 | static void hdmirx_get_pix_fmt(struct rk_hdmirx_dev *hdmirx_dev) |
|---|
| 616 | 627 | { |
|---|
| 617 | 628 | u32 val; |
|---|
| 629 | + int timeout = 10; |
|---|
| 618 | 630 | struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; |
|---|
| 619 | 631 | |
|---|
| 632 | +try_loop: |
|---|
| 620 | 633 | val = hdmirx_readl(hdmirx_dev, DMA_STATUS11); |
|---|
| 621 | 634 | hdmirx_dev->pix_fmt = val & HDMIRX_FORMAT_MASK; |
|---|
| 622 | 635 | |
|---|
| .. | .. |
|---|
| 635 | 648 | break; |
|---|
| 636 | 649 | |
|---|
| 637 | 650 | default: |
|---|
| 651 | + if (timeout-- > 0) { |
|---|
| 652 | + usleep_range(200 * 1000, 200 * 1010); |
|---|
| 653 | + v4l2_err(v4l2_dev, "%s: get format failed, read again!\n", __func__); |
|---|
| 654 | + goto try_loop; |
|---|
| 655 | + } |
|---|
| 656 | + hdmirx_dev->pix_fmt = HDMIRX_RGB888; |
|---|
| 657 | + hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24; |
|---|
| 638 | 658 | v4l2_err(v4l2_dev, |
|---|
| 639 | 659 | "%s: err pix_fmt: %d, set RGB888 as default\n", |
|---|
| 640 | 660 | __func__, hdmirx_dev->pix_fmt); |
|---|
| 641 | | - hdmirx_dev->pix_fmt = HDMIRX_RGB888; |
|---|
| 642 | | - hdmirx_dev->cur_fmt_fourcc = V4L2_PIX_FMT_BGR24; |
|---|
| 643 | 661 | break; |
|---|
| 644 | 662 | } |
|---|
| 645 | 663 | |
|---|
| .. | .. |
|---|
| 880 | 898 | struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; |
|---|
| 881 | 899 | u32 last_w, last_h; |
|---|
| 882 | 900 | struct v4l2_bt_timings *bt = &timings->bt; |
|---|
| 901 | + enum hdmirx_pix_fmt last_fmt; |
|---|
| 883 | 902 | |
|---|
| 884 | 903 | last_w = 0; |
|---|
| 885 | 904 | last_h = 0; |
|---|
| 905 | + last_fmt = HDMIRX_RGB888; |
|---|
| 906 | + |
|---|
| 886 | 907 | for (i = 0; i < try_cnt; i++) { |
|---|
| 887 | 908 | ret = hdmirx_get_detected_timings(hdmirx_dev, timings, from_dma); |
|---|
| 888 | 909 | |
|---|
| .. | .. |
|---|
| 891 | 912 | last_h = bt->height; |
|---|
| 892 | 913 | } |
|---|
| 893 | 914 | |
|---|
| 894 | | - if (ret || (last_w != bt->width) || (last_h != bt->height)) |
|---|
| 915 | + if (ret || (last_w != bt->width) || (last_h != bt->height) |
|---|
| 916 | + || (last_fmt != hdmirx_dev->pix_fmt)) |
|---|
| 895 | 917 | cnt = 0; |
|---|
| 896 | 918 | else |
|---|
| 897 | 919 | cnt++; |
|---|
| .. | .. |
|---|
| 901 | 923 | |
|---|
| 902 | 924 | last_w = bt->width; |
|---|
| 903 | 925 | last_h = bt->height; |
|---|
| 926 | + last_fmt = hdmirx_dev->pix_fmt; |
|---|
| 904 | 927 | usleep_range(10*1000, 10*1100); |
|---|
| 905 | 928 | } |
|---|
| 906 | 929 | |
|---|
| .. | .. |
|---|
| 1545 | 1568 | } |
|---|
| 1546 | 1569 | |
|---|
| 1547 | 1570 | hdmirx_reset_dma(hdmirx_dev); |
|---|
| 1548 | | - usleep_range(200*1000, 200*1010); |
|---|
| 1571 | + usleep_range(500*1000, 500*1010); |
|---|
| 1549 | 1572 | hdmirx_format_change(hdmirx_dev); |
|---|
| 1550 | 1573 | |
|---|
| 1551 | 1574 | return 0; |
|---|
| .. | .. |
|---|
| 2349 | 2372 | FIFO_UNDERFLOW_INT_EN | |
|---|
| 2350 | 2373 | HDMIRX_AXI_ERROR_INT_EN, 0); |
|---|
| 2351 | 2374 | hdmirx_reset_dma(hdmirx_dev); |
|---|
| 2375 | + hdmirx_interrupts_setup(hdmirx_dev, false); |
|---|
| 2352 | 2376 | v4l2_event_queue(&stream->vdev, &evt_signal_lost); |
|---|
| 2353 | 2377 | if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_stop) |
|---|
| 2354 | 2378 | hdmirx_dev->hdcp->hdcp_stop(hdmirx_dev->hdcp); |
|---|
| .. | .. |
|---|
| 2459 | 2483 | hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_FORCE, 0x0); |
|---|
| 2460 | 2484 | } |
|---|
| 2461 | 2485 | |
|---|
| 2486 | +/* |
|---|
| 2487 | + * In the normal preview, some scenarios will trigger the change interrupt |
|---|
| 2488 | + * by mistake, and the trigger source of the interrupt needs to be detected |
|---|
| 2489 | + * to avoid the problem. |
|---|
| 2490 | + */ |
|---|
| 2462 | 2491 | static void pkt_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev, |
|---|
| 2463 | 2492 | int status, bool *handled) |
|---|
| 2464 | 2493 | { |
|---|
| 2465 | 2494 | struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; |
|---|
| 2495 | + u32 pre_fmt_fourcc = hdmirx_dev->cur_fmt_fourcc; |
|---|
| 2496 | + u32 pre_color_range = hdmirx_dev->cur_color_range; |
|---|
| 2497 | + u32 pre_color_space = hdmirx_dev->cur_color_space; |
|---|
| 2466 | 2498 | |
|---|
| 2467 | 2499 | if ((status & PKTDEC_AVIIF_CHG_IRQ)) { |
|---|
| 2468 | | - process_signal_change(hdmirx_dev); |
|---|
| 2500 | + hdmirx_get_color_range(hdmirx_dev); |
|---|
| 2501 | + hdmirx_get_color_space(hdmirx_dev); |
|---|
| 2502 | + hdmirx_get_pix_fmt(hdmirx_dev); |
|---|
| 2503 | + if (hdmirx_dev->cur_fmt_fourcc != pre_fmt_fourcc || |
|---|
| 2504 | + hdmirx_dev->cur_color_range != pre_color_range || |
|---|
| 2505 | + hdmirx_dev->cur_color_space != pre_color_space) { |
|---|
| 2506 | + process_signal_change(hdmirx_dev); |
|---|
| 2507 | + } |
|---|
| 2469 | 2508 | v4l2_dbg(2, debug, v4l2_dev, "%s: ptk0_st:%#x\n", |
|---|
| 2470 | 2509 | __func__, status); |
|---|
| 2471 | 2510 | *handled = true; |
|---|
| .. | .. |
|---|
| 3158 | 3197 | struct rk_hdmirx_dev, |
|---|
| 3159 | 3198 | delayed_work_audio); |
|---|
| 3160 | 3199 | struct hdmirx_audiostate *as = &hdmirx_dev->audio_state; |
|---|
| 3161 | | - u32 fs_audio, ch_audio; |
|---|
| 3200 | + u32 fs_audio, ch_audio, sample_flat; |
|---|
| 3162 | 3201 | int cur_state, init_state, pre_state, fifo_status2; |
|---|
| 3163 | 3202 | unsigned long delay = 200; |
|---|
| 3164 | 3203 | |
|---|
| .. | .. |
|---|
| 3223 | 3262 | } |
|---|
| 3224 | 3263 | } |
|---|
| 3225 | 3264 | as->pre_state = cur_state; |
|---|
| 3265 | + |
|---|
| 3266 | + sample_flat = hdmirx_readl(hdmirx_dev, AUDIO_PROC_STATUS1) & AUD_SAMPLE_FLAT; |
|---|
| 3267 | + hdmirx_update_bits(hdmirx_dev, AUDIO_PROC_CONFIG0, I2S_EN, sample_flat ? 0 : I2S_EN); |
|---|
| 3268 | + |
|---|
| 3226 | 3269 | exit: |
|---|
| 3227 | 3270 | schedule_delayed_work_on(hdmirx_dev->bound_cpu, |
|---|
| 3228 | 3271 | &hdmirx_dev->delayed_work_audio, |
|---|
| .. | .. |
|---|
| 3243 | 3286 | plugin = tx_5v_power_present(hdmirx_dev); |
|---|
| 3244 | 3287 | v4l2_dbg(1, debug, v4l2_dev, "%s: plugin:%d\n", __func__, plugin); |
|---|
| 3245 | 3288 | if (plugin) { |
|---|
| 3246 | | - hdmirx_interrupts_setup(hdmirx_dev, false); |
|---|
| 3247 | 3289 | hdmirx_submodule_init(hdmirx_dev); |
|---|
| 3248 | 3290 | hdmirx_update_bits(hdmirx_dev, SCDC_CONFIG, POWERPROVIDED, |
|---|
| 3249 | 3291 | POWERPROVIDED); |
|---|
| .. | .. |
|---|
| 4280 | 4322 | if (ret) |
|---|
| 4281 | 4323 | goto err_unreg_video_dev; |
|---|
| 4282 | 4324 | |
|---|
| 4283 | | - hdmirx_dev->classdev = device_create_with_groups(hdmirx_class, |
|---|
| 4325 | + hdmirx_dev->classdev = device_create_with_groups(rk_hdmirx_class(), |
|---|
| 4284 | 4326 | dev, MKDEV(0, 0), |
|---|
| 4285 | 4327 | hdmirx_dev, |
|---|
| 4286 | 4328 | hdmirx_groups, |
|---|
| .. | .. |
|---|
| 4438 | 4480 | |
|---|
| 4439 | 4481 | static int __init hdmirx_init(void) |
|---|
| 4440 | 4482 | { |
|---|
| 4441 | | - hdmirx_class = class_create(THIS_MODULE, "hdmirx"); |
|---|
| 4442 | | - if (IS_ERR(hdmirx_class)) |
|---|
| 4443 | | - return PTR_ERR(hdmirx_class); |
|---|
| 4444 | 4483 | return platform_driver_register(&hdmirx_driver); |
|---|
| 4445 | 4484 | } |
|---|
| 4446 | 4485 | module_init(hdmirx_init); |
|---|
| .. | .. |
|---|
| 4448 | 4487 | static void __exit hdmirx_exit(void) |
|---|
| 4449 | 4488 | { |
|---|
| 4450 | 4489 | platform_driver_unregister(&hdmirx_driver); |
|---|
| 4451 | | - class_destroy(hdmirx_class); |
|---|
| 4452 | 4490 | } |
|---|
| 4453 | 4491 | module_exit(hdmirx_exit); |
|---|
| 4454 | 4492 | |
|---|