.. | .. |
---|
49 | 49 | #define LT7911D_LINK_FREQ 400000000 |
---|
50 | 50 | #define LT7911D_PIXEL_RATE 400000000 |
---|
51 | 51 | |
---|
| 52 | +#ifdef LT7911D_OUT_RGB |
---|
| 53 | +#define LT7911D_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 |
---|
| 54 | +#else |
---|
| 55 | +#define LT7911D_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 |
---|
| 56 | +#endif |
---|
| 57 | + |
---|
52 | 58 | #define LT7911D_NAME "LT7911D" |
---|
53 | 59 | |
---|
54 | 60 | static const s64 link_freq_menu_items[] = { |
---|
.. | .. |
---|
73 | 79 | struct clk *xvclk; |
---|
74 | 80 | struct gpio_desc *reset_gpio; |
---|
75 | 81 | struct gpio_desc *plugin_det_gpio; |
---|
76 | | - struct gpio_desc *hpd_ctl_gpio; |
---|
77 | 82 | struct gpio_desc *power_gpio; |
---|
78 | 83 | struct work_struct work_i2c_poll; |
---|
79 | 84 | struct timer_list timer; |
---|
.. | .. |
---|
472 | 477 | return 0; |
---|
473 | 478 | } |
---|
474 | 479 | |
---|
475 | | -static void lt7911d_config_hpd(struct v4l2_subdev *sd) |
---|
476 | | -{ |
---|
477 | | - struct lt7911d_state *lt7911d = to_state(sd); |
---|
478 | | - bool plugin; |
---|
479 | | - |
---|
480 | | - plugin = tx_5v_power_present(sd); |
---|
481 | | - v4l2_dbg(2, debug, sd, "%s: plugin: %d\n", __func__, plugin); |
---|
482 | | - |
---|
483 | | - if (plugin) { |
---|
484 | | - gpiod_set_value(lt7911d->hpd_ctl_gpio, 1); |
---|
485 | | - } else { |
---|
486 | | - lt7911d->nosignal = true; |
---|
487 | | - gpiod_set_value(lt7911d->hpd_ctl_gpio, 0); |
---|
488 | | - } |
---|
489 | | -} |
---|
490 | | - |
---|
491 | 480 | static void lt7911d_delayed_work_enable_hotplug(struct work_struct *work) |
---|
492 | 481 | { |
---|
493 | 482 | struct delayed_work *dwork = to_delayed_work(work); |
---|
.. | .. |
---|
495 | 484 | struct lt7911d_state, delayed_work_enable_hotplug); |
---|
496 | 485 | struct v4l2_subdev *sd = <7911d->sd; |
---|
497 | 486 | |
---|
498 | | - lt7911d_config_hpd(sd); |
---|
| 487 | + v4l2_ctrl_s_ctrl(lt7911d->detect_tx_5v_ctrl, tx_5v_power_present(sd)); |
---|
499 | 488 | } |
---|
500 | 489 | |
---|
501 | 490 | static void lt7911d_delayed_work_res_change(struct work_struct *work) |
---|
.. | .. |
---|
577 | 566 | v4l2_subdev_notify_event(sd, <7911d_ev_fmt); |
---|
578 | 567 | } |
---|
579 | 568 | |
---|
580 | | -static int lt7911d_get_ctrl(struct v4l2_ctrl *ctrl) |
---|
581 | | -{ |
---|
582 | | - int ret = -1; |
---|
583 | | - struct lt7911d_state *lt7911d = container_of(ctrl->handler, |
---|
584 | | - struct lt7911d_state, hdl); |
---|
585 | | - struct v4l2_subdev *sd = &(lt7911d->sd); |
---|
586 | | - |
---|
587 | | - if (ctrl->id == V4L2_CID_DV_RX_POWER_PRESENT) { |
---|
588 | | - ret = tx_5v_power_present(sd); |
---|
589 | | - *ctrl->p_new.p_s32 = ret; |
---|
590 | | - } |
---|
591 | | - |
---|
592 | | - return ret; |
---|
593 | | -} |
---|
594 | | - |
---|
595 | 569 | static int lt7911d_isr(struct v4l2_subdev *sd, u32 status, bool *handled) |
---|
596 | 570 | { |
---|
597 | 571 | struct lt7911d_state *lt7911d = to_state(sd); |
---|
.. | .. |
---|
615 | 589 | static irqreturn_t plugin_detect_irq_handler(int irq, void *dev_id) |
---|
616 | 590 | { |
---|
617 | 591 | struct lt7911d_state *lt7911d = dev_id; |
---|
618 | | - struct v4l2_subdev *sd = <7911d->sd; |
---|
619 | 592 | |
---|
620 | 593 | /* control hpd output level after 25ms */ |
---|
621 | 594 | schedule_delayed_work(<7911d->delayed_work_enable_hotplug, |
---|
622 | 595 | HZ / 40); |
---|
623 | | - tx_5v_power_present(sd); |
---|
624 | 596 | |
---|
625 | 597 | return IRQ_HANDLED; |
---|
626 | 598 | } |
---|
.. | .. |
---|
748 | 720 | } |
---|
749 | 721 | |
---|
750 | 722 | static int lt7911d_g_mbus_config(struct v4l2_subdev *sd, |
---|
751 | | - struct v4l2_mbus_config *cfg) |
---|
| 723 | + unsigned int pad, struct v4l2_mbus_config *cfg) |
---|
752 | 724 | { |
---|
753 | 725 | struct lt7911d_state *lt7911d = to_state(sd); |
---|
754 | 726 | |
---|
755 | | - cfg->type = V4L2_MBUS_CSI2; |
---|
| 727 | + cfg->type = V4L2_MBUS_CSI2_DPHY; |
---|
756 | 728 | cfg->flags = V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | |
---|
757 | 729 | V4L2_MBUS_CSI2_CHANNEL_0; |
---|
758 | 730 | |
---|
.. | .. |
---|
790 | 762 | { |
---|
791 | 763 | switch (code->index) { |
---|
792 | 764 | case 0: |
---|
793 | | - code->code = MEDIA_BUS_FMT_UYVY8_2X8; |
---|
| 765 | + code->code = LT7911D_MEDIA_BUS_FMT; |
---|
794 | 766 | break; |
---|
795 | 767 | |
---|
796 | 768 | default: |
---|
.. | .. |
---|
807 | 779 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
---|
808 | 780 | return -EINVAL; |
---|
809 | 781 | |
---|
810 | | - if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8) |
---|
| 782 | + if (fse->code != LT7911D_MEDIA_BUS_FMT) |
---|
811 | 783 | return -EINVAL; |
---|
812 | 784 | |
---|
813 | 785 | fse->min_width = supported_modes[fse->index].width; |
---|
.. | .. |
---|
848 | 820 | if (fie->index >= ARRAY_SIZE(supported_modes)) |
---|
849 | 821 | return -EINVAL; |
---|
850 | 822 | |
---|
851 | | - if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) |
---|
852 | | - return -EINVAL; |
---|
| 823 | + fie->code = LT7911D_MEDIA_BUS_FMT; |
---|
853 | 824 | |
---|
854 | 825 | fie->width = supported_modes[fie->index].width; |
---|
855 | 826 | fie->height = supported_modes[fie->index].height; |
---|
.. | .. |
---|
902 | 873 | return ret; |
---|
903 | 874 | |
---|
904 | 875 | switch (code) { |
---|
905 | | - case MEDIA_BUS_FMT_UYVY8_2X8: |
---|
| 876 | + case LT7911D_MEDIA_BUS_FMT: |
---|
906 | 877 | break; |
---|
907 | 878 | |
---|
908 | 879 | default: |
---|
.. | .. |
---|
951 | 922 | case RKMODULE_GET_MODULE_INFO: |
---|
952 | 923 | lt7911d_get_module_inf(lt7911d, (struct rkmodule_inf *)arg); |
---|
953 | 924 | break; |
---|
| 925 | + case RKMODULE_GET_HDMI_MODE: |
---|
| 926 | + *(int *)arg = RKMODULE_HDMIIN_MODE; |
---|
| 927 | + break; |
---|
954 | 928 | default: |
---|
955 | 929 | ret = -ENOIOCTLCMD; |
---|
956 | 930 | break; |
---|
.. | .. |
---|
966 | 940 | void __user *up = compat_ptr(arg); |
---|
967 | 941 | struct rkmodule_inf *inf; |
---|
968 | 942 | long ret; |
---|
| 943 | + int *seq; |
---|
969 | 944 | |
---|
970 | 945 | switch (cmd) { |
---|
971 | 946 | case RKMODULE_GET_MODULE_INFO: |
---|
.. | .. |
---|
983 | 958 | } |
---|
984 | 959 | kfree(inf); |
---|
985 | 960 | break; |
---|
| 961 | + case RKMODULE_GET_HDMI_MODE: |
---|
| 962 | + seq = kzalloc(sizeof(*seq), GFP_KERNEL); |
---|
| 963 | + if (!seq) { |
---|
| 964 | + ret = -ENOMEM; |
---|
| 965 | + return ret; |
---|
| 966 | + } |
---|
986 | 967 | |
---|
| 968 | + ret = lt7911d_ioctl(sd, cmd, seq); |
---|
| 969 | + if (!ret) { |
---|
| 970 | + ret = copy_to_user(up, seq, sizeof(*seq)); |
---|
| 971 | + if (ret) |
---|
| 972 | + ret = -EFAULT; |
---|
| 973 | + } |
---|
| 974 | + kfree(seq); |
---|
| 975 | + break; |
---|
987 | 976 | default: |
---|
988 | 977 | ret = -ENOIOCTLCMD; |
---|
989 | 978 | break; |
---|
.. | .. |
---|
992 | 981 | return ret; |
---|
993 | 982 | } |
---|
994 | 983 | #endif |
---|
995 | | - |
---|
996 | | -static const struct v4l2_ctrl_ops lt7911d_ctrl_ops = { |
---|
997 | | - .g_volatile_ctrl = lt7911d_get_ctrl, |
---|
998 | | -}; |
---|
999 | 984 | |
---|
1000 | 985 | static const struct v4l2_subdev_core_ops lt7911d_core_ops = { |
---|
1001 | 986 | .interrupt_service_routine = lt7911d_isr, |
---|
.. | .. |
---|
1012 | 997 | .s_dv_timings = lt7911d_s_dv_timings, |
---|
1013 | 998 | .g_dv_timings = lt7911d_g_dv_timings, |
---|
1014 | 999 | .query_dv_timings = lt7911d_query_dv_timings, |
---|
1015 | | - .g_mbus_config = lt7911d_g_mbus_config, |
---|
1016 | 1000 | .s_stream = lt7911d_s_stream, |
---|
1017 | 1001 | .g_frame_interval = lt7911d_g_frame_interval, |
---|
1018 | 1002 | }; |
---|
.. | .. |
---|
1025 | 1009 | .get_fmt = lt7911d_get_fmt, |
---|
1026 | 1010 | .enum_dv_timings = lt7911d_enum_dv_timings, |
---|
1027 | 1011 | .dv_timings_cap = lt7911d_dv_timings_cap, |
---|
| 1012 | + .get_mbus_config = lt7911d_g_mbus_config, |
---|
1028 | 1013 | }; |
---|
1029 | 1014 | |
---|
1030 | 1015 | static const struct v4l2_subdev_ops lt7911d_ops = { |
---|
.. | .. |
---|
1055 | 1040 | .flags = V4L2_CTRL_FLAG_READ_ONLY, |
---|
1056 | 1041 | }; |
---|
1057 | 1042 | |
---|
1058 | | -static void lt7911d_reset(struct lt7911d_state *lt7911d) |
---|
1059 | | -{ |
---|
1060 | | - gpiod_set_value(lt7911d->reset_gpio, 0); |
---|
1061 | | - usleep_range(2000, 2100); |
---|
1062 | | - gpiod_set_value(lt7911d->reset_gpio, 1); |
---|
1063 | | - usleep_range(120*1000, 121*1000); |
---|
1064 | | - gpiod_set_value(lt7911d->reset_gpio, 0); |
---|
1065 | | - usleep_range(300*1000, 310*1000); |
---|
1066 | | -} |
---|
1067 | | - |
---|
1068 | 1043 | static int lt7911d_init_v4l2_ctrls(struct lt7911d_state *lt7911d) |
---|
1069 | 1044 | { |
---|
1070 | 1045 | struct v4l2_subdev *sd; |
---|
.. | .. |
---|
1084 | 1059 | 0, LT7911D_PIXEL_RATE, 1, LT7911D_PIXEL_RATE); |
---|
1085 | 1060 | |
---|
1086 | 1061 | lt7911d->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<7911d->hdl, |
---|
1087 | | - <7911d_ctrl_ops, V4L2_CID_DV_RX_POWER_PRESENT, |
---|
| 1062 | + NULL, V4L2_CID_DV_RX_POWER_PRESENT, |
---|
1088 | 1063 | 0, 1, 0, 0); |
---|
1089 | | - if (lt7911d->detect_tx_5v_ctrl) |
---|
1090 | | - lt7911d->detect_tx_5v_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; |
---|
1091 | 1064 | |
---|
1092 | 1065 | lt7911d->audio_sampling_rate_ctrl = |
---|
1093 | 1066 | v4l2_ctrl_new_custom(<7911d->hdl, |
---|
.. | .. |
---|
1119 | 1092 | { |
---|
1120 | 1093 | struct device *dev = <7911d->i2c_client->dev; |
---|
1121 | 1094 | struct device_node *node = dev->of_node; |
---|
1122 | | - struct v4l2_fwnode_endpoint *endpoint; |
---|
| 1095 | + struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; |
---|
1123 | 1096 | struct device_node *ep; |
---|
1124 | 1097 | int ret; |
---|
1125 | 1098 | |
---|
.. | .. |
---|
1160 | 1133 | return ret; |
---|
1161 | 1134 | } |
---|
1162 | 1135 | |
---|
1163 | | - lt7911d->hpd_ctl_gpio = devm_gpiod_get_optional(dev, "hpd-ctl", |
---|
1164 | | - GPIOD_OUT_HIGH); |
---|
1165 | | - if (IS_ERR(lt7911d->hpd_ctl_gpio)) { |
---|
1166 | | - dev_err(dev, "failed to get hpd ctl gpio\n"); |
---|
1167 | | - ret = PTR_ERR(lt7911d->hpd_ctl_gpio); |
---|
1168 | | - return ret; |
---|
1169 | | - } |
---|
1170 | | - |
---|
1171 | 1136 | ep = of_graph_get_next_endpoint(dev->of_node, NULL); |
---|
1172 | 1137 | if (!ep) { |
---|
1173 | 1138 | dev_err(dev, "missing endpoint node\n"); |
---|
1174 | 1139 | return -EINVAL; |
---|
1175 | 1140 | } |
---|
1176 | 1141 | |
---|
1177 | | - endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep)); |
---|
1178 | | - if (IS_ERR(endpoint)) { |
---|
| 1142 | + ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint); |
---|
| 1143 | + if (ret) { |
---|
1179 | 1144 | dev_err(dev, "failed to parse endpoint\n"); |
---|
1180 | | - ret = PTR_ERR(endpoint); |
---|
1181 | | - return ret; |
---|
| 1145 | + goto put_node; |
---|
1182 | 1146 | } |
---|
1183 | 1147 | |
---|
1184 | | - if (endpoint->bus_type != V4L2_MBUS_CSI2 || |
---|
1185 | | - endpoint->bus.mipi_csi2.num_data_lanes == 0) { |
---|
| 1148 | + if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY || |
---|
| 1149 | + endpoint.bus.mipi_csi2.num_data_lanes == 0) { |
---|
1186 | 1150 | dev_err(dev, "missing CSI-2 properties in endpoint\n"); |
---|
1187 | 1151 | ret = -EINVAL; |
---|
1188 | 1152 | goto free_endpoint; |
---|
.. | .. |
---|
1201 | 1165 | goto free_endpoint; |
---|
1202 | 1166 | } |
---|
1203 | 1167 | |
---|
1204 | | - lt7911d->csi_lanes_in_use = endpoint->bus.mipi_csi2.num_data_lanes; |
---|
1205 | | - lt7911d->bus = endpoint->bus.mipi_csi2; |
---|
| 1168 | + lt7911d->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes; |
---|
| 1169 | + lt7911d->bus = endpoint.bus.mipi_csi2; |
---|
1206 | 1170 | lt7911d->enable_hdcp = false; |
---|
1207 | 1171 | |
---|
1208 | | - gpiod_set_value(lt7911d->hpd_ctl_gpio, 0); |
---|
1209 | 1172 | gpiod_set_value(lt7911d->power_gpio, 1); |
---|
1210 | | - lt7911d_reset(lt7911d); |
---|
| 1173 | + usleep_range(2000, 3000); |
---|
| 1174 | + gpiod_set_value(lt7911d->reset_gpio, 0); |
---|
1211 | 1175 | |
---|
1212 | 1176 | ret = 0; |
---|
1213 | 1177 | |
---|
1214 | 1178 | free_endpoint: |
---|
1215 | | - v4l2_fwnode_endpoint_free(endpoint); |
---|
| 1179 | + v4l2_fwnode_endpoint_free(&endpoint); |
---|
| 1180 | +put_node: |
---|
| 1181 | + of_node_put(ep); |
---|
1216 | 1182 | return ret; |
---|
1217 | 1183 | } |
---|
1218 | 1184 | #else |
---|
.. | .. |
---|
1266 | 1232 | sd = <7911d->sd; |
---|
1267 | 1233 | lt7911d->i2c_client = client; |
---|
1268 | 1234 | lt7911d->cur_mode = &supported_modes[0]; |
---|
1269 | | - lt7911d->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8; |
---|
| 1235 | + lt7911d->mbus_fmt_code = LT7911D_MEDIA_BUS_FMT; |
---|
1270 | 1236 | |
---|
1271 | 1237 | err = lt7911d_probe_of(lt7911d); |
---|
1272 | 1238 | if (err) { |
---|
.. | .. |
---|
1277 | 1243 | err = lt7911d_check_chip_id(lt7911d); |
---|
1278 | 1244 | if (err < 0) |
---|
1279 | 1245 | return err; |
---|
1280 | | - |
---|
1281 | | - lt7911d_reset(lt7911d); |
---|
1282 | 1246 | |
---|
1283 | 1247 | mutex_init(<7911d->confctl_mutex); |
---|
1284 | 1248 | err = lt7911d_init_v4l2_ctrls(lt7911d); |
---|
.. | .. |
---|
1357 | 1321 | goto err_work_queues; |
---|
1358 | 1322 | } |
---|
1359 | 1323 | |
---|
1360 | | - lt7911d_config_hpd(sd); |
---|
1361 | 1324 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
---|
1362 | 1325 | client->addr << 1, client->adapter->name); |
---|
1363 | 1326 | |
---|