^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Dingxian Wen <shawn.wen@rock-chips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * V0.0X01.0X00 first version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * V0.0X01.0X01 fix if plugin_gpio was not used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * V0.0X01.0X02 modify driver init level to late_initcall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/hdmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/rk-camera-module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/v4l2-dv-timings.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/v4l2-controls_rockchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <media/v4l2-dv-timings.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/v4l2-fwnode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "lt6911uxc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define LT6911UXC_NAME "LT6911UXC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define LT6911UXC_LINK_FREQ_HIGH 400000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define LT6911UXC_LINK_FREQ_LOW 200000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define LT6911UXC_PIXEL_RATE 400000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define I2C_MAX_XFER_SIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_PARM_DESC(debug, "debug level (0-2)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static const s64 link_freq_menu_items[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) LT6911UXC_LINK_FREQ_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) LT6911UXC_LINK_FREQ_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct lt6911uxc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct clk *xvclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct delayed_work delayed_work_enable_hotplug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct delayed_work delayed_work_res_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct gpio_desc *hpd_ctl_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct gpio_desc *plugin_det_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct gpio_desc *power_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct i2c_client *i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct mutex confctl_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct v4l2_ctrl *audio_present_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct v4l2_ctrl *audio_sampling_rate_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct v4l2_ctrl *detect_tx_5v_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct v4l2_ctrl *link_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct v4l2_ctrl *pixel_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct v4l2_ctrl_handler hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct v4l2_dv_timings timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct v4l2_fwnode_bus_mipi_csi2 bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) const char *len_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const char *module_facing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const char *module_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const struct lt6911uxc_mode *cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) bool enable_hdcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bool nosignal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) bool is_audio_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int plugin_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u32 mbus_fmt_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u32 module_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 csi_lanes_in_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 audio_sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct lt6911uxc_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct v4l2_fract max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) u32 hts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) u32 vts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 exp_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .type = V4L2_DV_BT_656_1120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* keep this initialization for compatibility with GCC < 4.4.6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .reserved = { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) V4L2_DV_BT_CAP_PROGRESSIVE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) V4L2_DV_BT_CAP_INTERLACED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) V4L2_DV_BT_CAP_REDUCED_BLANKING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) V4L2_DV_BT_CAP_CUSTOM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct lt6911uxc_mode supported_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .width = 3840,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .height = 2160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .denominator = 300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .hts_def = 4400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .vts_def = 2250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .width = 1920,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .height = 1080,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .denominator = 600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .hts_def = 2200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .vts_def = 1125,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .width = 1920,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .height = 540,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .denominator = 600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .width = 1440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .height = 240,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .denominator = 600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .width = 1440,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .height = 288,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .denominator = 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .width = 1280,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .height = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .denominator = 600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .hts_def = 1650,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .vts_def = 750,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .width = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .height = 576,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .denominator = 500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .hts_def = 864,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .vts_def = 625,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .width = 720,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .height = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .denominator = 600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .hts_def = 858,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .vts_def = 525,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void lt6911uxc_format_change(struct v4l2_subdev *sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int lt6911uxc_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int lt6911uxc_s_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct v4l2_dv_timings *timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static inline struct lt6911uxc *to_state(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return container_of(sd, struct lt6911uxc, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct i2c_client *client = lt6911uxc->i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct i2c_msg msgs[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u8 bank = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u8 reg_addr = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 buf[2] = {0xFF, bank};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* write bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) msgs[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) msgs[0].len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) msgs[0].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* write reg addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) msgs[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) msgs[1].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) msgs[1].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) msgs[1].buf = ®_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* read data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) msgs[2].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) msgs[2].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) msgs[2].len = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) msgs[2].buf = values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (err != ARRAY_SIZE(msgs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) __func__, reg, client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct i2c_client *client = lt6911uxc->i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct i2c_msg msgs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u8 data[I2C_MAX_XFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u8 bank = reg >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 reg_addr = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 buf[2] = {0xFF, bank};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if ((1 + n) > I2C_MAX_XFER_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) n = I2C_MAX_XFER_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 1 + n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) data[0] = reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) data[i + 1] = values[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* write bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) msgs[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) msgs[0].len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) msgs[0].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* write reg data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) msgs[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) msgs[1].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) msgs[1].len = 1 + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) msgs[1].buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) __func__, reg, client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int i2c_rd8(struct v4l2_subdev *sd, u16 reg, u8 *val_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return i2c_rd(sd, reg, val_p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return i2c_wr(sd, reg, &val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void lt6911uxc_i2c_enable(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) i2c_wr8(sd, I2C_EN_REG, I2C_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void lt6911uxc_i2c_disable(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) i2c_wr8(sd, I2C_EN_REG, I2C_DISABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static inline bool tx_5v_power_present(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) bool ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int val, i, cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* if not use plugin det gpio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!lt6911uxc->plugin_det_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) val = gpiod_get_value(lt6911uxc->plugin_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (val > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) usleep_range(500, 600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = (cnt >= 3) ? true : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static inline bool no_signal(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) v4l2_dbg(1, debug, sd, "%s no signal:%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) lt6911uxc->nosignal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return lt6911uxc->nosignal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static inline bool audio_present(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return lt6911uxc->is_audio_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int get_audio_sampling_rate(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (no_signal(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return lt6911uxc->audio_sampling_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static inline unsigned int fps_calc(const struct v4l2_bt_timings *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!V4L2_DV_BT_FRAME_HEIGHT(t) || !V4L2_DV_BT_FRAME_WIDTH(t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return DIV_ROUND_CLOSEST((unsigned int)t->pixelclock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) V4L2_DV_BT_FRAME_HEIGHT(t) * V4L2_DV_BT_FRAME_WIDTH(t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static bool lt6911uxc_rcv_supported_res(struct v4l2_subdev *sd, u32 width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u32 height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if ((supported_modes[i].width == width) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) (supported_modes[i].height == height)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (i == ARRAY_SIZE(supported_modes)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) v4l2_err(sd, "%s do not support res wxh: %dx%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static int lt6911uxc_get_detected_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct v4l2_bt_timings *bt = &timings->bt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u32 hact, vact, htotal, vtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) u32 hbp, hs, hfp, vbp, vs, vfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) u32 pixel_clock, fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) u8 clk_h, clk_m, clk_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u8 value, val_h, val_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) u32 fw_ver, mipi_byte_clk, mipi_bitrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) u8 fw_a, fw_b, fw_c, fw_d, lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) memset(timings, 0, sizeof(struct v4l2_dv_timings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) lt6911uxc_i2c_enable(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) ret = i2c_rd8(sd, FW_VER_A, &fw_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ret |= i2c_rd8(sd, FW_VER_B, &fw_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret |= i2c_rd8(sd, FW_VER_C, &fw_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ret |= i2c_rd8(sd, FW_VER_D, &fw_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) v4l2_err(sd, "%s: I2C transform err!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) fw_ver = (fw_a << 24) | (fw_b << 16) | (fw_c << 8) | fw_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) v4l2_info(sd, "read fw_version:%#x", fw_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) i2c_wr8(sd, INT_COMPARE_REG, RECEIVED_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) i2c_rd8(sd, INT_STATUS_86A3, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) i2c_rd8(sd, INT_STATUS_86A5, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) v4l2_info(sd, "int status REG_86A3:%#x, REG_86A5:%#x\n", val_h, val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) i2c_rd8(sd, HDMI_VERSION, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) i2c_rd8(sd, TMDS_CLK_H, &clk_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) i2c_rd8(sd, TMDS_CLK_M, &clk_m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) i2c_rd8(sd, TMDS_CLK_L, &clk_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pixel_clock = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (value & BIT(0)) /* HDMI 2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pixel_clock *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) i2c_rd8(sd, MIPI_LANES, &lanes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) lt6911uxc->csi_lanes_in_use = lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) i2c_wr8(sd, FM1_DET_CLK_SRC_SEL, AD_LMTX_WRITE_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) i2c_rd8(sd, FREQ_METER_H, &clk_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) i2c_rd8(sd, FREQ_METER_M, &clk_m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) i2c_rd8(sd, FREQ_METER_L, &clk_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) mipi_byte_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mipi_bitrate = mipi_byte_clk * 8 / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) v4l2_info(sd, "MIPI Byte clk: %dKHz, MIPI bitrate: %dMbps, lanes:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mipi_byte_clk, mipi_bitrate, lanes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) i2c_rd8(sd, HTOTAL_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) i2c_rd8(sd, HTOTAL_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) htotal = ((val_h << 8) | val_l) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) i2c_rd8(sd, VTOTAL_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) i2c_rd8(sd, VTOTAL_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) vtotal = (val_h << 8) | val_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) i2c_rd8(sd, HACT_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) i2c_rd8(sd, HACT_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) hact = ((val_h << 8) | val_l) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) i2c_rd8(sd, VACT_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) i2c_rd8(sd, VACT_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) vact = (val_h << 8) | val_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) i2c_rd8(sd, HS_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) i2c_rd8(sd, HS_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) hs = ((val_h << 8) | val_l) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) i2c_rd8(sd, VS, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) vs = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) i2c_rd8(sd, HFP_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) i2c_rd8(sd, HFP_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) hfp = ((val_h << 8) | val_l) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) i2c_rd8(sd, VFP, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) vfp = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) i2c_rd8(sd, HBP_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) i2c_rd8(sd, HBP_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) hbp = ((val_h << 8) | val_l) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) i2c_rd8(sd, VBP, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) vbp = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) lt6911uxc_i2c_disable(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (!lt6911uxc_rcv_supported_res(sd, hact, vact)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) lt6911uxc->nosignal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) lt6911uxc->nosignal = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) i2c_rd8(sd, AUDIO_IN_STATUS, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) lt6911uxc->is_audio_present = (value & BIT(5)) ? true : false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) i2c_rd8(sd, AUDIO_SAMPLE_RATAE_H, &val_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) i2c_rd8(sd, AUDIO_SAMPLE_RATAE_L, &val_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) lt6911uxc->audio_sampling_rate = ((val_h << 8) | val_l) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) v4l2_info(sd, "is_audio_present: %d, audio_sampling_rate: %dKhz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) lt6911uxc->is_audio_present,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) lt6911uxc->audio_sampling_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) timings->type = V4L2_DV_BT_656_1120;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) bt->width = hact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) bt->height = vact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) bt->vsync = vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) bt->hsync = hs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) bt->pixelclock = pixel_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) bt->hfrontporch = hfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) bt->vfrontporch = vfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) bt->hbackporch = hbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) bt->vbackporch = vbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) fps = fps_calc(bt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* for interlaced res 1080i 576i 480i*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if ((hact == 1920 && vact == 540) || (hact == 1440 && vact == 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) || (hact == 1440 && vact == 240)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) bt->interlaced = V4L2_DV_INTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) bt->height *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) bt->il_vsync = bt->vsync + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) bt->interlaced = V4L2_DV_PROGRESSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) v4l2_info(sd, "act:%dx%d, total:%dx%d, pixclk:%d, fps:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) hact, vact, htotal, vtotal, pixel_clock, fps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) v4l2_info(sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d, inerlaced:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) bt->vsync, bt->vbackporch, bt->interlaced);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static void lt6911uxc_config_hpd(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) bool plugin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) plugin = tx_5v_power_present(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) v4l2_dbg(2, debug, sd, "%s: plugin: %d\n", __func__, plugin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (plugin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) lt6911uxc->nosignal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static void lt6911uxc_delayed_work_enable_hotplug(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct delayed_work *dwork = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct lt6911uxc *lt6911uxc = container_of(dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct lt6911uxc, delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct v4l2_subdev *sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) v4l2_dbg(2, debug, sd, "%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) v4l2_ctrl_s_ctrl(lt6911uxc->detect_tx_5v_ctrl, tx_5v_power_present(sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) lt6911uxc_config_hpd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static void lt6911uxc_delayed_work_res_change(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct delayed_work *dwork = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct lt6911uxc *lt6911uxc = container_of(dwork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct lt6911uxc, delayed_work_res_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct v4l2_subdev *sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) v4l2_dbg(2, debug, sd, "%s:\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) lt6911uxc_format_change(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int lt6911uxc_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return v4l2_ctrl_s_ctrl(lt6911uxc->detect_tx_5v_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) tx_5v_power_present(sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static int lt6911uxc_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return v4l2_ctrl_s_ctrl(lt6911uxc->audio_sampling_rate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) get_audio_sampling_rate(sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int lt6911uxc_s_ctrl_audio_present(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return v4l2_ctrl_s_ctrl(lt6911uxc->audio_present_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) audio_present(sd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int lt6911uxc_update_controls(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ret |= lt6911uxc_s_ctrl_detect_tx_5v(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ret |= lt6911uxc_s_ctrl_audio_sampling_rate(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ret |= lt6911uxc_s_ctrl_audio_present(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static inline void enable_stream(struct v4l2_subdev *sd, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) v4l2_dbg(2, debug, sd, "%s: %sable\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) __func__, enable ? "en" : "dis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void lt6911uxc_format_change(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct v4l2_dv_timings timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) const struct v4l2_event lt6911uxc_ev_fmt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .type = V4L2_EVENT_SOURCE_CHANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (lt6911uxc_get_detected_timings(sd, &timings)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) enable_stream(sd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (!v4l2_match_dv_timings(<6911uxc->timings, &timings, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) enable_stream(sd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* automatically set timing rather than set by user */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) lt6911uxc_s_dv_timings(sd, &timings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) v4l2_print_dv_timings(sd->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) "Format_change: New format: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) &timings, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (sd->devnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) v4l2_subdev_notify_event(sd, <6911uxc_ev_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int lt6911uxc_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) schedule_delayed_work(<6911uxc->delayed_work_res_change, HZ / 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *handled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static irqreturn_t lt6911uxc_res_change_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct lt6911uxc *lt6911uxc = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) bool handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) lt6911uxc_isr(<6911uxc->sd, 0, &handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return handled ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static irqreturn_t plugin_detect_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct lt6911uxc *lt6911uxc = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct v4l2_subdev *sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* control hpd output level after 25ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) schedule_delayed_work(<6911uxc->delayed_work_enable_hotplug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) HZ / 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) tx_5v_power_present(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static int lt6911uxc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct v4l2_event_subscription *sub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) switch (sub->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case V4L2_EVENT_SOURCE_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case V4L2_EVENT_CTRL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int lt6911uxc_g_input_status(struct v4l2_subdev *sd, u32 *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static int lt6911uxc_s_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (!timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) v4l2_print_dv_timings(sd->name, "s_dv_timings: ", timings, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (v4l2_match_dv_timings(<6911uxc->timings, timings, 0, false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) v4l2_dbg(1, debug, sd, "%s: no change\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (!v4l2_valid_dv_timings(timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) <6911uxc_timings_cap, NULL, NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) lt6911uxc->timings = *timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) enable_stream(sd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int lt6911uxc_g_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *timings = lt6911uxc->timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static int lt6911uxc_enum_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct v4l2_enum_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (timings->pad != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return v4l2_enum_dv_timings_cap(timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) <6911uxc_timings_cap, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static int lt6911uxc_query_dv_timings(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct v4l2_dv_timings *timings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) *timings = lt6911uxc->timings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) v4l2_print_dv_timings(sd->name, "query_dv_timings: ", timings, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!v4l2_valid_dv_timings(timings, <6911uxc_timings_cap, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static int lt6911uxc_dv_timings_cap(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct v4l2_dv_timings_cap *cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (cap->pad != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) *cap = lt6911uxc_timings_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int lt6911uxc_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct v4l2_mbus_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) cfg->type = V4L2_MBUS_CSI2_DPHY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_CHANNEL_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) switch (lt6911uxc->csi_lanes_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) cfg->flags |= V4L2_MBUS_CSI2_1_LANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cfg->flags |= V4L2_MBUS_CSI2_2_LANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) cfg->flags |= V4L2_MBUS_CSI2_3_LANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) cfg->flags |= V4L2_MBUS_CSI2_4_LANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int lt6911uxc_s_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) enable_stream(sd, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static int lt6911uxc_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) switch (code->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) code->code = MEDIA_BUS_FMT_UYVY8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int lt6911uxc_enum_frame_sizes(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (fse->index >= ARRAY_SIZE(supported_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) fse->min_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) fse->max_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) fse->max_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) fse->min_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static int lt6911uxc_enum_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) struct v4l2_subdev_frame_interval_enum *fie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (fie->index >= ARRAY_SIZE(supported_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) fie->width = supported_modes[fie->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) fie->height = supported_modes[fie->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) fie->interval = supported_modes[fie->index].max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mutex_lock(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) format->format.code = lt6911uxc->mbus_fmt_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) format->format.width = lt6911uxc->timings.bt.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) format->format.height = lt6911uxc->timings.bt.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) format->format.field =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) lt6911uxc->timings.bt.interlaced ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) format->format.colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) mutex_unlock(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field mode:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) __func__, format->format.code, format->format.width, format->format.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) (format->format.field == V4L2_FIELD_INTERLACED) ? "I" : "P");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct v4l2_mbus_framefmt *framefmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return abs(mode->width - framefmt->width) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) abs(mode->height - framefmt->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) static const struct lt6911uxc_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) lt6911uxc_find_best_fit(struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct v4l2_mbus_framefmt *framefmt = &fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int cur_best_fit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int cur_best_fit_dist = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dist = lt6911uxc_get_reso_dist(&supported_modes[i], framefmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) cur_best_fit_dist = dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) cur_best_fit = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return &supported_modes[cur_best_fit];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) const struct lt6911uxc_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* is overwritten by get_fmt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) u32 code = format->format.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int ret = lt6911uxc_get_fmt(sd, cfg, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) format->format.code = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) switch (code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (format->which == V4L2_SUBDEV_FORMAT_TRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) lt6911uxc->mbus_fmt_code = format->format.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) mode = lt6911uxc_find_best_fit(format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) lt6911uxc->cur_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) enable_stream(sd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (((mode->width == 720) && (mode->height == 576)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ((mode->width == 720) && (mode->height == 480)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) __v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) v4l2_dbg(1, debug, sd, "%s res wxh:%dx%d, link freq:%llu", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) mode->width, mode->height, link_freq_menu_items[index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static int lt6911uxc_g_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) const struct lt6911uxc_mode *mode = lt6911uxc->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) mutex_lock(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) fi->interval = mode->max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) mutex_unlock(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static void lt6911uxc_get_module_inf(struct lt6911uxc *lt6911uxc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct rkmodule_inf *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) memset(inf, 0, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) strscpy(inf->base.sensor, LT6911UXC_NAME, sizeof(inf->base.sensor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) strscpy(inf->base.module, lt6911uxc->module_name, sizeof(inf->base.module));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) strscpy(inf->base.lens, lt6911uxc->len_name, sizeof(inf->base.lens));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) lt6911uxc_get_module_inf(lt6911uxc, (struct rkmodule_inf *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) case RKMODULE_GET_HDMI_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) *(int *)arg = RKMODULE_HDMIIN_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static long lt6911uxc_compat_ioctl32(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) void __user *up = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct rkmodule_inf *inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int *seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) inf = kzalloc(sizeof(*inf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!inf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ret = lt6911uxc_ioctl(sd, cmd, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) ret = copy_to_user(up, inf, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) kfree(inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) case RKMODULE_GET_HDMI_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) seq = kzalloc(sizeof(*seq), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (!seq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ret = lt6911uxc_ioctl(sd, cmd, seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) ret = copy_to_user(up, seq, sizeof(*seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) kfree(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static const struct v4l2_subdev_core_ops lt6911uxc_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) .interrupt_service_routine = lt6911uxc_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) .subscribe_event = lt6911uxc_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) .unsubscribe_event = v4l2_event_subdev_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) .ioctl = lt6911uxc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .compat_ioctl32 = lt6911uxc_compat_ioctl32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static const struct v4l2_subdev_video_ops lt6911uxc_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) .g_input_status = lt6911uxc_g_input_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .s_dv_timings = lt6911uxc_s_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .g_dv_timings = lt6911uxc_g_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .query_dv_timings = lt6911uxc_query_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .s_stream = lt6911uxc_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .g_frame_interval = lt6911uxc_g_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static const struct v4l2_subdev_pad_ops lt6911uxc_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .enum_mbus_code = lt6911uxc_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) .enum_frame_size = lt6911uxc_enum_frame_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) .enum_frame_interval = lt6911uxc_enum_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) .set_fmt = lt6911uxc_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) .get_fmt = lt6911uxc_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) .enum_dv_timings = lt6911uxc_enum_dv_timings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) .dv_timings_cap = lt6911uxc_dv_timings_cap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) .get_mbus_config = lt6911uxc_g_mbus_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static const struct v4l2_subdev_ops lt6911uxc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .core = <6911uxc_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .video = <6911uxc_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .pad = <6911uxc_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static const struct v4l2_ctrl_config lt6911uxc_ctrl_audio_sampling_rate = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) .id = RK_V4L2_CID_AUDIO_SAMPLING_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) .name = "Audio sampling rate",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .max = 768000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .flags = V4L2_CTRL_FLAG_READ_ONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static const struct v4l2_ctrl_config lt6911uxc_ctrl_audio_present = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .id = RK_V4L2_CID_AUDIO_PRESENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) .name = "Audio present",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) .type = V4L2_CTRL_TYPE_BOOLEAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) .max = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) .flags = V4L2_CTRL_FLAG_READ_ONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static void lt6911uxc_reset(struct lt6911uxc *lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) gpiod_set_value(lt6911uxc->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) usleep_range(2000, 2100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) gpiod_set_value(lt6911uxc->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) usleep_range(120*1000, 121*1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) gpiod_set_value(lt6911uxc->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) usleep_range(300*1000, 310*1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ret = v4l2_ctrl_handler_init(<6911uxc->hdl, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) lt6911uxc->link_freq = v4l2_ctrl_new_int_menu(<6911uxc->hdl, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) V4L2_CID_LINK_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ARRAY_SIZE(link_freq_menu_items) - 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) link_freq_menu_items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) v4l2_ctrl_new_std(<6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<6911uxc->hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) NULL, V4L2_CID_DV_RX_POWER_PRESENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 0, 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) lt6911uxc->audio_sampling_rate_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) v4l2_ctrl_new_custom(<6911uxc->hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) <6911uxc_ctrl_audio_sampling_rate, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) lt6911uxc->audio_present_ctrl = v4l2_ctrl_new_custom(<6911uxc->hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) <6911uxc_ctrl_audio_present, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) sd->ctrl_handler = <6911uxc->hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (lt6911uxc->hdl.error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ret = lt6911uxc->hdl.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (lt6911uxc_update_controls(sd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int lt6911uxc_check_chip_id(struct lt6911uxc *lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct device *dev = <6911uxc->i2c_client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct v4l2_subdev *sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) u8 fw_a, fw_b, fw_c, fw_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) u8 id_h, id_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) u32 chipid, fw_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) lt6911uxc_i2c_enable(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ret = i2c_rd8(sd, CHIPID_L, &id_l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ret |= i2c_rd8(sd, CHIPID_H, &id_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) ret |= i2c_rd8(sd, FW_VER_A, &fw_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) ret |= i2c_rd8(sd, FW_VER_B, &fw_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ret |= i2c_rd8(sd, FW_VER_C, &fw_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ret |= i2c_rd8(sd, FW_VER_D, &fw_d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) lt6911uxc_i2c_disable(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) chipid = (id_h << 8) | id_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (chipid != LT6911UXC_CHIPID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) dev_err(dev, "chipid err, read:%#x, expect:%#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) chipid, LT6911UXC_CHIPID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) fw_ver = (fw_a << 24) | (fw_b << 16) | (fw_c << 8) | fw_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) dev_info(dev, "chipid ok, id:%#x, fw_ver:%#x", chipid, fw_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) dev_err(dev, "%s i2c trans failed!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static int lt6911uxc_parse_of(struct lt6911uxc *lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct device *dev = <6911uxc->i2c_client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct device_node *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) <6911uxc->module_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) <6911uxc->module_facing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) <6911uxc->module_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) <6911uxc->len_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) dev_err(dev, "could not get module information!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) lt6911uxc->power_gpio = devm_gpiod_get_optional(dev, "power",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (IS_ERR(lt6911uxc->power_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) dev_err(dev, "failed to get power gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) ret = PTR_ERR(lt6911uxc->power_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) lt6911uxc->reset_gpio = devm_gpiod_get_optional(dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (IS_ERR(lt6911uxc->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dev_err(dev, "failed to get reset gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ret = PTR_ERR(lt6911uxc->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) lt6911uxc->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (IS_ERR(lt6911uxc->plugin_det_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) dev_err(dev, "failed to get plugin det gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) ret = PTR_ERR(lt6911uxc->plugin_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) lt6911uxc->hpd_ctl_gpio = devm_gpiod_get_optional(dev, "hpd-ctl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (IS_ERR(lt6911uxc->hpd_ctl_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) dev_err(dev, "failed to get hpd ctl gpio\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) ret = PTR_ERR(lt6911uxc->hpd_ctl_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) ep = of_graph_get_next_endpoint(dev->of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!ep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) dev_err(dev, "missing endpoint node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) dev_err(dev, "failed to parse endpoint\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) goto put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) endpoint.bus.mipi_csi2.num_data_lanes == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) dev_err(dev, "missing CSI-2 properties in endpoint\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) goto free_endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) lt6911uxc->xvclk = devm_clk_get(dev, "xvclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (IS_ERR(lt6911uxc->xvclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) dev_err(dev, "failed to get xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) goto free_endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ret = clk_prepare_enable(lt6911uxc->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) dev_err(dev, "Failed! to enable xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) goto free_endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) lt6911uxc->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) lt6911uxc->bus = endpoint.bus.mipi_csi2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) lt6911uxc->enable_hdcp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) gpiod_set_value(lt6911uxc->power_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) lt6911uxc_reset(lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) free_endpoint:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) v4l2_fwnode_endpoint_free(&endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) of_node_put(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) static inline int lt6911uxc_parse_of(struct lt6911uxc *lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static int lt6911uxc_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct lt6911uxc *lt6911uxc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) char facing[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) dev_info(dev, "driver version: %02x.%02x.%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) DRIVER_VERSION >> 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) (DRIVER_VERSION & 0xff00) >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) DRIVER_VERSION & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) lt6911uxc = devm_kzalloc(dev, sizeof(struct lt6911uxc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (!lt6911uxc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) sd = <6911uxc->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) lt6911uxc->i2c_client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) lt6911uxc->cur_mode = &supported_modes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) lt6911uxc->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) err = lt6911uxc_parse_of(lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) v4l2_err(sd, "lt6911uxc_parse_of failed! err:%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) err = lt6911uxc_check_chip_id(lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /* after the CPU actively accesses the lt6911uxc through I2C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) * a reset operation is required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) lt6911uxc_reset(lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) mutex_init(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) err = lt6911uxc_init_v4l2_ctrls(lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) goto err_free_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) client->flags |= I2C_CLIENT_SCCB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) v4l2_i2c_subdev_init(sd, client, <6911uxc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) lt6911uxc->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) err = media_entity_pads_init(&sd->entity, 1, <6911uxc->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) v4l2_err(sd, "media entity init failed! err: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) goto err_free_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) memset(facing, 0, sizeof(facing));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (strcmp(lt6911uxc->module_facing, "back") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) facing[0] = 'b';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) facing[0] = 'f';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) lt6911uxc->module_index, facing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) LT6911UXC_NAME, dev_name(sd->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) err = v4l2_async_register_subdev_sensor_common(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) goto err_clean_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) INIT_DELAYED_WORK(<6911uxc->delayed_work_enable_hotplug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) lt6911uxc_delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) INIT_DELAYED_WORK(<6911uxc->delayed_work_res_change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) lt6911uxc_delayed_work_res_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (lt6911uxc->i2c_client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) v4l2_dbg(1, debug, sd, "cfg lt6911uxc irq!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) err = devm_request_threaded_irq(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) lt6911uxc->i2c_client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) NULL, lt6911uxc_res_change_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) "lt6911uxc", lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) v4l2_err(sd, "request irq failed! err:%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) goto err_work_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) v4l2_err(sd, "no irq cfg failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) goto err_work_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) lt6911uxc->plugin_irq = gpiod_to_irq(lt6911uxc->plugin_det_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (lt6911uxc->plugin_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) dev_err(dev, "failed to get plugin det irq, maybe no use\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) err = devm_request_threaded_irq(dev, lt6911uxc->plugin_irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) plugin_detect_irq_handler, IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) IRQF_TRIGGER_RISING | IRQF_ONESHOT, "lt6911uxc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) lt6911uxc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) dev_err(dev, "failed to register plugin det irq (%d), maybe no use\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) goto err_work_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) lt6911uxc_config_hpd(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) client->addr << 1, client->adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) err_work_queues:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) cancel_delayed_work(<6911uxc->delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) cancel_delayed_work(<6911uxc->delayed_work_res_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) err_clean_entity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) err_free_hdl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) v4l2_ctrl_handler_free(<6911uxc->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) mutex_destroy(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) static int lt6911uxc_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) struct lt6911uxc *lt6911uxc = to_state(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) cancel_delayed_work_sync(<6911uxc->delayed_work_enable_hotplug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) cancel_delayed_work_sync(<6911uxc->delayed_work_res_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) v4l2_device_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) v4l2_ctrl_handler_free(<6911uxc->hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) mutex_destroy(<6911uxc->confctl_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) clk_disable_unprepare(lt6911uxc->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) static const struct of_device_id lt6911uxc_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) { .compatible = "lontium,lt6911uxc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) MODULE_DEVICE_TABLE(of, lt6911uxc_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) static struct i2c_driver lt6911uxc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) .name = LT6911UXC_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) .of_match_table = of_match_ptr(lt6911uxc_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) .probe = lt6911uxc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) .remove = lt6911uxc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) static int __init lt6911uxc_driver_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) return i2c_add_driver(<6911uxc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) static void __exit lt6911uxc_driver_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) i2c_del_driver(<6911uxc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) late_initcall(lt6911uxc_driver_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) module_exit(lt6911uxc_driver_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) MODULE_LICENSE("GPL v2");