From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:45:28 +0000
Subject: [PATCH] add boot partition  size

---
 kernel/drivers/media/i2c/lt6911uxc.c |  134 +++++++++++++++++++++++++-------------------
 1 files changed, 77 insertions(+), 57 deletions(-)

diff --git a/kernel/drivers/media/i2c/lt6911uxc.c b/kernel/drivers/media/i2c/lt6911uxc.c
index 88ce0ca..23da66e 100644
--- a/kernel/drivers/media/i2c/lt6911uxc.c
+++ b/kernel/drivers/media/i2c/lt6911uxc.c
@@ -3,6 +3,9 @@
  * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
  *
  * Author: Dingxian Wen <shawn.wen@rock-chips.com>
+ * V0.0X01.0X00 first version.
+ * V0.0X01.0X01 fix if plugin_gpio was not used.
+ * V0.0X01.0X02 modify driver init level to late_initcall.
  */
 
 #include <linux/clk.h>
@@ -21,6 +24,7 @@
 #include <linux/version.h>
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
+#include <linux/compat.h>
 #include <media/v4l2-controls_rockchip.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -29,7 +33,7 @@
 #include <media/v4l2-fwnode.h>
 #include "lt6911uxc.h"
 
-#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x0)
+#define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x2)
 #define LT6911UXC_NAME			"LT6911UXC"
 
 #define LT6911UXC_LINK_FREQ_HIGH	400000000
@@ -37,6 +41,12 @@
 #define LT6911UXC_PIXEL_RATE		400000000
 
 #define I2C_MAX_XFER_SIZE		128
+
+#ifdef LT6911UXC_OUT_RGB
+#define LT6911UXC_MEDIA_BUS_FMT		MEDIA_BUS_FMT_BGR888_1X24
+#else
+#define LT6911UXC_MEDIA_BUS_FMT		MEDIA_BUS_FMT_UYVY8_2X8
+#endif
 
 static int debug;
 module_param(debug, int, 0644);
@@ -286,14 +296,27 @@
 
 static inline bool tx_5v_power_present(struct v4l2_subdev *sd)
 {
-	int val;
+	bool ret;
+	int val, i, cnt;
 	struct lt6911uxc *lt6911uxc = to_state(sd);
 
-	val = gpiod_get_value(lt6911uxc->plugin_det_gpio);
-	v4l2_dbg(1, debug, sd, "%s plug det: %s!\n", __func__,
-			(val > 0) ? "int" : "out");
+	/* if not use plugin det gpio */
+	if (!lt6911uxc->plugin_det_gpio)
+		return true;
 
-	return  (val > 0);
+	cnt = 0;
+	for (i = 0; i < 5; i++) {
+		val = gpiod_get_value(lt6911uxc->plugin_det_gpio);
+
+		if (val > 0)
+			cnt++;
+		usleep_range(500, 600);
+	}
+
+	ret = (cnt >= 3) ? true : false;
+	v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
+
+	return ret;
 }
 
 static inline bool no_signal(struct v4l2_subdev *sd)
@@ -505,6 +528,8 @@
 	struct v4l2_subdev *sd = &lt6911uxc->sd;
 
 	v4l2_dbg(2, debug, sd, "%s:\n", __func__);
+
+	v4l2_ctrl_s_ctrl(lt6911uxc->detect_tx_5v_ctrl, tx_5v_power_present(sd));
 	lt6911uxc_config_hpd(sd);
 }
 
@@ -587,21 +612,6 @@
 
 	if (sd->devnode)
 		v4l2_subdev_notify_event(sd, &lt6911uxc_ev_fmt);
-}
-
-static int lt6911uxc_get_ctrl(struct v4l2_ctrl *ctrl)
-{
-	int ret = -1;
-	struct lt6911uxc *lt6911uxc = container_of(ctrl->handler,
-			struct lt6911uxc, hdl);
-	struct v4l2_subdev *sd = &(lt6911uxc->sd);
-
-	if (ctrl->id == V4L2_CID_DV_RX_POWER_PRESENT) {
-		ret = tx_5v_power_present(sd);
-		*ctrl->p_new.p_s32 = ret;
-	}
-
-	return ret;
 }
 
 static int lt6911uxc_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
@@ -738,12 +748,12 @@
 	return 0;
 }
 
-static int lt6911uxc_g_mbus_config(struct v4l2_subdev *sd,
+static int lt6911uxc_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
 			     struct v4l2_mbus_config *cfg)
 {
 	struct lt6911uxc *lt6911uxc = to_state(sd);
 
-	cfg->type = V4L2_MBUS_CSI2;
+	cfg->type = V4L2_MBUS_CSI2_DPHY;
 	cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_CHANNEL_0;
 
 	switch (lt6911uxc->csi_lanes_in_use) {
@@ -780,7 +790,7 @@
 {
 	switch (code->index) {
 	case 0:
-		code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+		code->code = LT6911UXC_MEDIA_BUS_FMT;
 		break;
 
 	default:
@@ -797,7 +807,7 @@
 	if (fse->index >= ARRAY_SIZE(supported_modes))
 		return -EINVAL;
 
-	if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
+	if (fse->code != LT6911UXC_MEDIA_BUS_FMT)
 		return -EINVAL;
 
 	fse->min_width  = supported_modes[fse->index].width;
@@ -815,8 +825,7 @@
 	if (fie->index >= ARRAY_SIZE(supported_modes))
 		return -EINVAL;
 
-	if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8)
-		return -EINVAL;
+	fie->code = LT6911UXC_MEDIA_BUS_FMT;
 
 	fie->width = supported_modes[fie->index].width;
 	fie->height = supported_modes[fie->index].height;
@@ -893,7 +902,7 @@
 		return ret;
 
 	switch (code) {
-	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case LT6911UXC_MEDIA_BUS_FMT:
 		break;
 
 	default:
@@ -952,6 +961,9 @@
 	case RKMODULE_GET_MODULE_INFO:
 		lt6911uxc_get_module_inf(lt6911uxc, (struct rkmodule_inf *)arg);
 		break;
+	case RKMODULE_GET_HDMI_MODE:
+		*(int *)arg = RKMODULE_HDMIIN_MODE;
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -967,6 +979,7 @@
 	void __user *up = compat_ptr(arg);
 	struct rkmodule_inf *inf;
 	long ret;
+	int *seq;
 
 	switch (cmd) {
 	case RKMODULE_GET_MODULE_INFO:
@@ -984,7 +997,21 @@
 		}
 		kfree(inf);
 		break;
+	case RKMODULE_GET_HDMI_MODE:
+		seq = kzalloc(sizeof(*seq), GFP_KERNEL);
+		if (!seq) {
+			ret = -ENOMEM;
+			return ret;
+		}
 
+		ret = lt6911uxc_ioctl(sd, cmd, seq);
+		if (!ret) {
+			ret = copy_to_user(up, seq, sizeof(*seq));
+			if (ret)
+				ret = -EFAULT;
+		}
+		kfree(seq);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -993,10 +1020,6 @@
 	return ret;
 }
 #endif
-
-static const struct v4l2_ctrl_ops lt6911uxc_ctrl_ops = {
-	.g_volatile_ctrl = lt6911uxc_get_ctrl,
-};
 
 static const struct v4l2_subdev_core_ops lt6911uxc_core_ops = {
 	.interrupt_service_routine = lt6911uxc_isr,
@@ -1013,7 +1036,6 @@
 	.s_dv_timings = lt6911uxc_s_dv_timings,
 	.g_dv_timings = lt6911uxc_g_dv_timings,
 	.query_dv_timings = lt6911uxc_query_dv_timings,
-	.g_mbus_config = lt6911uxc_g_mbus_config,
 	.s_stream = lt6911uxc_s_stream,
 	.g_frame_interval = lt6911uxc_g_frame_interval,
 };
@@ -1026,6 +1048,7 @@
 	.get_fmt = lt6911uxc_get_fmt,
 	.enum_dv_timings = lt6911uxc_enum_dv_timings,
 	.dv_timings_cap = lt6911uxc_dv_timings_cap,
+	.get_mbus_config = lt6911uxc_g_mbus_config,
 };
 
 static const struct v4l2_subdev_ops lt6911uxc_ops = {
@@ -1084,10 +1107,8 @@
 			  0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
 
 	lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt6911uxc->hdl,
-			&lt6911uxc_ctrl_ops, V4L2_CID_DV_RX_POWER_PRESENT,
+			NULL, V4L2_CID_DV_RX_POWER_PRESENT,
 			0, 1, 0, 0);
-	if (lt6911uxc->detect_tx_5v_ctrl)
-		lt6911uxc->detect_tx_5v_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
 
 	lt6911uxc->audio_sampling_rate_ctrl =
 		v4l2_ctrl_new_custom(&lt6911uxc->hdl,
@@ -1153,7 +1174,7 @@
 {
 	struct device *dev = &lt6911uxc->i2c_client->dev;
 	struct device_node *node = dev->of_node;
-	struct v4l2_fwnode_endpoint *endpoint;
+	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
 	struct device_node *ep;
 	int ret;
 
@@ -1209,15 +1230,14 @@
 		return ret;
 	}
 
-	endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep));
-	if (IS_ERR(endpoint)) {
+	ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
+	if (ret) {
 		dev_err(dev, "failed to parse endpoint\n");
-		ret = PTR_ERR(endpoint);
-		return ret;
+		goto put_node;
 	}
 
-	if (endpoint->bus_type != V4L2_MBUS_CSI2 ||
-			endpoint->bus.mipi_csi2.num_data_lanes == 0) {
+	if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY ||
+			endpoint.bus.mipi_csi2.num_data_lanes == 0) {
 		dev_err(dev, "missing CSI-2 properties in endpoint\n");
 		ret = -EINVAL;
 		goto free_endpoint;
@@ -1236,8 +1256,8 @@
 		goto free_endpoint;
 	}
 
-	lt6911uxc->csi_lanes_in_use = endpoint->bus.mipi_csi2.num_data_lanes;
-	lt6911uxc->bus = endpoint->bus.mipi_csi2;
+	lt6911uxc->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes;
+	lt6911uxc->bus = endpoint.bus.mipi_csi2;
 	lt6911uxc->enable_hdcp = false;
 
 	gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 0);
@@ -1247,7 +1267,9 @@
 	ret = 0;
 
 free_endpoint:
-	v4l2_fwnode_endpoint_free(endpoint);
+	v4l2_fwnode_endpoint_free(&endpoint);
+put_node:
+	of_node_put(ep);
 	return ret;
 }
 #else
@@ -1260,6 +1282,8 @@
 static int lt6911uxc_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
+	struct v4l2_dv_timings default_timing =
+				V4L2_DV_BT_CEA_640X480P59_94;
 	struct lt6911uxc *lt6911uxc;
 	struct v4l2_subdev *sd;
 	struct device *dev = &client->dev;
@@ -1277,8 +1301,9 @@
 
 	sd = &lt6911uxc->sd;
 	lt6911uxc->i2c_client = client;
+	lt6911uxc->timings = default_timing;
 	lt6911uxc->cur_mode = &supported_modes[0];
-	lt6911uxc->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
+	lt6911uxc->mbus_fmt_code = LT6911UXC_MEDIA_BUS_FMT;
 
 	err = lt6911uxc_parse_of(lt6911uxc);
 	if (err) {
@@ -1353,20 +1378,15 @@
 	}
 
 	lt6911uxc->plugin_irq = gpiod_to_irq(lt6911uxc->plugin_det_gpio);
-	if (lt6911uxc->plugin_irq < 0) {
-		dev_err(dev, "failed to get plugin det irq\n");
-		err = lt6911uxc->plugin_irq;
-		goto err_work_queues;
-	}
+	if (lt6911uxc->plugin_irq < 0)
+		dev_err(dev, "failed to get plugin det irq, maybe no use\n");
 
 	err = devm_request_threaded_irq(dev, lt6911uxc->plugin_irq, NULL,
 			plugin_detect_irq_handler, IRQF_TRIGGER_FALLING |
 			IRQF_TRIGGER_RISING | IRQF_ONESHOT, "lt6911uxc",
 			lt6911uxc);
-	if (err) {
-		dev_err(dev, "failed to register plugin det irq (%d)\n", err);
-		goto err_work_queues;
-	}
+	if (err)
+		dev_err(dev, "failed to register plugin det irq (%d), maybe no use\n", err);
 
 	err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
 	if (err) {
@@ -1439,7 +1459,7 @@
 	i2c_del_driver(&lt6911uxc_driver);
 }
 
-device_initcall_sync(lt6911uxc_driver_init);
+late_initcall(lt6911uxc_driver_init);
 module_exit(lt6911uxc_driver_exit);
 
 MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");

--
Gitblit v1.6.2