| .. | .. |
|---|
| 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 | |
|---|