[PX3][Android7.1]调试笔记DM5150支持(二)

DM5150支持(一)

平台 内核版本 安卓版本
PX3 Linux4.4 Android7.1

文章目录

Kconfig

目录drivers/media/video/Kconfig

+config SOC_CAMERA_DM5150
+        tristate "dm5150 camera support for rockchip"
+        depends on SOC_CAMERA && I2C
+        help
+          This is a dm5150 camera driver for rockchip

Makefile

目录drivers/media/video/Makefile

 obj-$(CONFIG_SOC_CAMERA_DM5886)		+= dm5886.o
+obj-$(CONFIG_SOC_CAMERA_DM5150)     += dm5150.o
 obj-$(CONFIG_SOC_CAMERA_ADV7181)	+= adv7181.o

驱动

目录drivers/media/video/dm5150.c

#include "generic_sensor.h"
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include "dm5150.h"
+
+static int version = KERNEL_VERSION(9,2,25);
+module_param(version, int, S_IRUGO);
+
+#if 0
+#define DBG(x...) printk(KERN_INFO x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
+static int debug = 7;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do {		\
+	if (debug >= level)				\
+		printk(KERN_WARNING fmt, ## arg);	\
+} while (0)
+#define debug_printk(format, ...) dprintk(1, format, ## __VA_ARGS__)
+/* Sensor Driver Configuration Begin */
+#define SENSOR_NAME RK29_CAM_SENSOR_DM5150
+#define SENSOR_V4L2_IDENT V4L2_IDENT_DM5150
+#define SENSOR_ID 0x3b
+#define SENSOR_BUS_PARAM  (SOCAM_MASTER |\
+                           SOCAM_PCLK_SAMPLE_RISING|\
+                           SOCAM_HSYNC_ACTIVE_HIGH|\
+					       SOCAM_VSYNC_ACTIVE_HIGH |	\
+                           SOCAM_DATA_ACTIVE_HIGH |\
+                           SOCAM_DATAWIDTH_8  |\
+                           SOCAM_MCLK_24MHZ)
+
+static int SENSOR_PREVIEW_W = 720;
+static int SENSOR_PREVIEW_H = 576;
+static volatile v4l2_std_id std_last_g = V4L2_STD_PAL;
+
+static struct rk_camera_device_signal_config dev_info[] = {
+	{
+		.type = RK_CAMERA_DEVICE_CVBS_PAL,
+		.code = V4L2_MBUS_FMT_UYVY8_2X8,
+		.crop = {
+			.top = 0,   
+			.left = 0, 
+			.width = 720,
+			.height = 576, 
+		}
+	}
+};
+
+static struct rk_camera_device_defrect defrects[] = {
+	{
+		.width = 720,
+		.height = 480,
+		.defrect = {
+			.top = 2,	
+			.left = 0,	
+			.width = 720,
+			.height = 480,
+		},
+		.interface = "cvbs_ntsc"
+	},
+	{
+		.width = 720,
+		.height = 576,
+		.defrect = {
+			.top = 0,
+			.left = 0,
+			.width = 720,
+			.height = 576
+		},
+		.interface = "cvbs_pal"
+	},
+};
+
+static struct rk_camera_device_channel_info channel_infos = {
+	.channel_total = 1,
+	.default_id = 0,
+	.channel_info = {
+		"cvbs 1",
+	}
+};
+
+static char input_mode[10] = "PAL";
+#define SENSOR_PREVIEW_FPS                   30000     // 30fps
+#define SENSOR_FULLRES_L_FPS                 7500      // 7.5fps
+#define SENSOR_FULLRES_H_FPS                 7500      // 7.5fps
+#define SENSOR_720P_FPS                      0
+#define SENSOR_1080P_FPS                     0
+
+#define SENSOR_REGISTER_LEN                  1         // sensor register address bytes
+#define SENSOR_VALUE_LEN                     1         // sensor register value bytes
+
+static unsigned int SensorConfiguration = (CFG_Effect | CFG_Scene);
+static unsigned int SensorChipID[] = {SENSOR_ID};
+/* Sensor Driver Configuration End */
+
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+#define SensorRegVal(a,b) CONS4(SensorReg,SENSOR_REGISTER_LEN,Val,SENSOR_VALUE_LEN)(a,b)
+#define sensor_write(client,reg,v) CONS4(sensor_write_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v))
+#define sensor_read(client,reg,v) CONS4(sensor_read_reg,SENSOR_REGISTER_LEN,val,SENSOR_VALUE_LEN)(client,(reg),(v))
+#define sensor_write_array generic_sensor_write_array
+static void dm5150_reinit_parameter(v4l2_std_id std,
+				     struct generic_sensor *sensor);
+static void dm5150_send_uevent(struct generic_sensor *sensor);
+
+struct sensor_parameter {
+	unsigned int PreviewDummyPixels;
+	unsigned int CaptureDummyPixels;
+	unsigned int preview_exposure;
+	unsigned short int preview_line_width;
+	unsigned short int preview_gain;
+
+	unsigned short int PreviewPclk;
+	unsigned short int CapturePclk;
+	char awb[6];
+};
+
+struct specific_sensor{
+	struct generic_sensor common_sensor;
+	//define user data below
+	struct sensor_parameter parameter;
+};
+
+static struct rk_sensor_reg sensor_check_id_data[] = {
+	SensorRegVal(0xff, 0x0),
+	SensorEnd
+};
+
+
+/* Sensor initial setting */
+static struct rk_sensor_reg sensor_init_data[] = {
+	SensorEnd
+};
+/* Senor full resolution setting: recommand for capture */
+static struct rk_sensor_reg sensor_fullres_lowfps_data[] = {
+	SensorEnd
+};
+/* Senor full resolution setting: recommand for video */
+static struct rk_sensor_reg sensor_fullres_highfps_data[] = {
+	SensorEnd
+};
+/* Preview resolution setting*/
+
+
+/* 1280x720 */
+static struct rk_sensor_reg sensor_720p[] = {
+	SensorEnd
+};
+
+/* 1920x1080 */
+static struct rk_sensor_reg sensor_1080p[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_softreset_data[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_preview_data[] = {
+	{0x51, 0x01},//bit[0]= '1' system reset
+	{0x32, 0x00},//bit[0]= '0' set the IC for 720(720*480 or 576) mode
+	{0x3b, 0x00},//disable auto detection line lock camera function
+	{0x3c, 0x05},//set line lock auto detection threshold
+	{0x08, 0x30},//set color burst difference threshold
+	{0x14, 0x16},//always tracking clkoffset
+	{0x17, 0x0a},//set Hsync track
+	{0x05, 0x20},//set Hsync threshold
+	{0x18, 0x23},//bit[0]= '1' auto update HSYNCTH
+	{0x39, 0xd2},//increase color AGC threshold
+	{0x3d, 0x40},//CCIR buffer reset
+	{0x3a, 0x90},//CAGC enable
+	{0x1a, 0x15},//burst detect option.
+	{0x06, 0x0a},//drive black panel when no video signal
+	{0x2b, 0x43},//NTSC mode, CCIR656 output 487 active line
+	{0x00, 0x8a},//bit[7] = '1' Reset, bit[3]= '1' Select VADC_A to VD. bit[1]= '1' Enable
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_WhiteB_Auto[] = {
+	SensorEnd
+};
+static	struct rk_sensor_reg sensor_WhiteB_Cloudy[] = {
+	SensorEnd
+};
+
+/* ClearDay Colour Temperature : 5000K - 6500K	*/
+static	struct rk_sensor_reg sensor_WhiteB_ClearDay[] = {
+	SensorEnd
+};
+/* Office Colour Temperature : 3500K - 5000K  */
+static	struct rk_sensor_reg sensor_WhiteB_TungstenLamp1[] = {
+	SensorEnd
+};
+/* Home Colour Temperature : 2500K - 3500K	*/
+static	struct rk_sensor_reg sensor_WhiteB_TungstenLamp2[] = {
+	SensorEnd
+};
+static struct rk_sensor_reg *sensor_WhiteBalanceSeqe[] = {
+	sensor_WhiteB_Auto,
+	sensor_WhiteB_TungstenLamp1,
+	sensor_WhiteB_TungstenLamp2,
+	sensor_WhiteB_ClearDay,
+	sensor_WhiteB_Cloudy,
+	NULL,
+};
+
+static struct rk_sensor_reg sensor_Brightness0[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Brightness1[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Brightness2[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Brightness3[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Brightness4[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Brightness5[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg *sensor_BrightnessSeqe[] = {
+	sensor_Brightness0,
+	sensor_Brightness1,
+	sensor_Brightness2,
+	sensor_Brightness3,
+	sensor_Brightness4,
+	sensor_Brightness5,
+	NULL,
+};
+
+static struct rk_sensor_reg sensor_Effect_Normal[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Effect_WandB[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Effect_Sepia[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Effect_Negative[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Effect_Bluish[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Effect_Green[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg *sensor_EffectSeqe[] = {
+	sensor_Effect_Normal,
+	sensor_Effect_WandB,
+	sensor_Effect_Negative,
+	sensor_Effect_Sepia,
+	sensor_Effect_Bluish,
+	sensor_Effect_Green,
+	NULL,
+};
+
+static struct rk_sensor_reg sensor_Exposure0[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure1[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure2[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure3[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure4[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure5[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Exposure6[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg *sensor_ExposureSeqe[] = {
+	sensor_Exposure0,
+	sensor_Exposure1,
+	sensor_Exposure2,
+	sensor_Exposure3,
+	sensor_Exposure4,
+	sensor_Exposure5,
+	sensor_Exposure6,
+	NULL,
+};
+
+static struct rk_sensor_reg sensor_Saturation0[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Saturation1[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Saturation2[] = {
+	SensorEnd
+};
+static struct rk_sensor_reg *sensor_SaturationSeqe[] = {
+	sensor_Saturation0,
+	sensor_Saturation1,
+	sensor_Saturation2,
+	NULL,
+};
+
+static struct rk_sensor_reg sensor_Contrast0[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Contrast1[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Contrast2[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Contrast3[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Contrast4[] = {
+	SensorEnd
+};
+
+
+static struct rk_sensor_reg sensor_Contrast5[] = {
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Contrast6[] = {
+	SensorEnd
+};
+static struct rk_sensor_reg *sensor_ContrastSeqe[] = {
+	sensor_Contrast0,
+	sensor_Contrast1,
+	sensor_Contrast2,
+	sensor_Contrast3,
+	sensor_Contrast4,
+	sensor_Contrast5,
+	sensor_Contrast6,
+	NULL,
+};
+static	struct rk_sensor_reg sensor_SceneAuto[] =
+{
+	SensorEnd
+};
+
+static	struct rk_sensor_reg sensor_SceneNight[] =
+{
+	SensorEnd
+};
+static struct rk_sensor_reg *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+static struct rk_sensor_reg sensor_Zoom0[] =
+{
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Zoom1[] =
+{
+	SensorEnd
+};
+
+static struct rk_sensor_reg sensor_Zoom2[] =
+{
+	SensorEnd
+};
+
+
+static struct rk_sensor_reg sensor_Zoom3[] =
+{
+	SensorEnd
+};
+static struct rk_sensor_reg *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+
+/*
+* User could be add v4l2_querymenu in sensor_controls by new_usr_v4l2menu
+*/
+static struct v4l2_querymenu sensor_menus[] =
+{
+};
+/*
+* User could be add v4l2_queryctrl in sensor_controls by new_user_v4l2ctrl
+*/
+static inline int dm5150_channel_set(struct i2c_client *client,
+				      struct sensor_v4l2ctrl_info_s *ctrl_info,
+				      struct v4l2_ext_control *ext_ctrl)
+{
+	struct generic_sensor *sensor = to_generic_sensor(client);
+	struct rk_sensor_sequence *sensor_series =
+		sensor->info_priv.sensor_series;
+	int series_num = sensor->info_priv.num_series;
+	int ret = 0;
+	int i;
+	int id;
+	int channel_ain;
+
+	DBG("\n====%s\n",__FUNCTION__);
+
+	if ((ext_ctrl->value < ctrl_info->qctrl->minimum) ||
+	    (ext_ctrl->value > ctrl_info->qctrl->maximum)) {
+		SENSOR_TR("%s(%d):channel(%d) is not support\n",__func__, __LINE__, ext_ctrl->value);
+		ret = -EINVAL;
+		goto end;
+	}
+	if (sensor->channel_id != ext_ctrl->value) {
+		SENSOR_TR("%s(%d):set channel(%d)!\n", __func__, __LINE__, ext_ctrl->value);
+		sensor->channel_id = ext_ctrl->value;
+		id = sensor->channel_id;
+		for (i = 0; i < series_num; i++)
+			if ((sensor_series[i].property == SEQUENCE_PREVIEW) && (sensor_series[i].data[0].reg != SEQCMD_END))
+				break;
+		if (strstr(channel_infos.channel_info[id], "cvbs")) {
+			ret = sscanf(channel_infos.channel_info[id], "%*s %d",&channel_ain);
+			if (IS_ERR_VALUE(ret)) {
+				SENSOR_TR("%s(%d): channel_infos err!\n", __func__, __LINE__);
+				ret = -EINVAL;
+				goto end;
+			}
+
+			sensor_series[i].data = sensor_preview_data;
+			sensor->info_priv.dev_sig_cnf.type = RK_CAMERA_DEVICE_CVBS_NTSC;
+			sensor->info_priv.dev_sig_cnf.code =V4L2_MBUS_FMT_UYVY8_2X8;
+			dm5150_reinit_parameter(V4L2_STD_NTSC, sensor);
+		}
+
+		generic_sensor_write_array(client, sensor_series[i].data);
+	}
+
+end:
+	return ret;
+}
+
+static inline int sensor_v4l2ctrl_inside_cb(struct soc_camera_device *icd,
+					    struct sensor_v4l2ctrl_info_s *ctrl_info,
+					    struct v4l2_ext_control *ext_ctrl,
+					    bool is_set)
+{
+	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+	struct generic_sensor *sensor = to_generic_sensor(client);
+	int ret = 0;
+
+	DBG("\n====%s\n",__FUNCTION__);
+
+	switch (ctrl_info->qctrl->id) {
+	case V4L2_CID_DEINTERLACE:
+		{
+			if (is_set) {
+				SENSOR_TR("deinterlace isn't support set!\n");
+				ret = -EINVAL;
+				goto cb_end;
+			} else {
+				if ((RK_CAMERA_DEVICE_BT601_8 == sensor->info_priv.dev_sig_cnf.type)) {
+					/* don't need deinterlace process */
+					ext_ctrl->value = 0;
+					ctrl_info->cur_value = 0;
+				} else {
+					ext_ctrl->value = 1;
+					ctrl_info->cur_value = 1;
+				}
+			}
+			break;
+		}
+	case V4L2_CID_CHANNEL:
+	{
+		if (is_set) {
+			ret = dm5150_channel_set(client, ctrl_info, ext_ctrl);
+			if (ret)
+				goto cb_end;
+		} else {
+			ext_ctrl->value = sensor->channel_id;
+			ctrl_info->cur_value = sensor->channel_id;
+		}
+		break;
+	}
+	case V4L2_CID_BRIGHTNESS:
+	{
+		sensor_write(client, DM5150_REG_BRIGHTNESS, ext_ctrl->value);
+		break;
+	}
+	case V4L2_CID_CONTRAST:
+	{
+		sensor_write(client, DM5150_REG_CONTRAST, ext_ctrl->value);
+		break;
+	}
+	case V4L2_CID_SATURATION:
+	{
+		sensor_write(client, DM5150_REG_SATURATION, ext_ctrl->value);
+		break;
+	}
+	case V4L2_CID_HUE:
+	{
+		sensor_write(client, DM5150_REG_HUE, ext_ctrl->value);
+		break;
+	}
+	default:
+		{
+			SENSOR_TR("%s(%d): cmd(0x%x) is unknown !\n",__func__, __LINE__, ctrl_info->qctrl->id);
+			ret = -EINVAL;
+		}
+	}
+
+cb_end:
+	return ret;
+}
+static struct sensor_v4l2ctrl_usr_s sensor_controls[] = {
+	{
+		{
+			V4L2_CID_DEINTERLACE,
+			V4L2_CTRL_TYPE_BOOLEAN,
+			"deinterlace",
+			0,
+			1,
+			1,
+			0
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+	{
+		{
+			V4L2_CID_CHANNEL,
+			V4L2_CTRL_TYPE_INTEGER,
+			"channel",
+			0,
+			4,
+			1,
+			0
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+	{
+		{
+			V4L2_CID_BRIGHTNESS,
+			V4L2_CTRL_TYPE_INTEGER,
+			"brightness",
+			0,
+			255,
+			1,
+			128
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+	{
+		{
+			V4L2_CID_CONTRAST,
+			V4L2_CTRL_TYPE_INTEGER,
+			"contrast",
+			0,
+			255,
+			1,
+			128
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+	{
+		{
+			V4L2_CID_SATURATION,
+			V4L2_CTRL_TYPE_INTEGER,
+			"saturation",
+			0,
+			255,
+			1,
+			128
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+	{
+		{
+			V4L2_CID_HUE,
+			V4L2_CTRL_TYPE_INTEGER,
+			"hue",
+			-128,
+			127,
+			1,
+			0
+		},
+		sensor_v4l2ctrl_inside_cb,
+		NULL
+	},
+};
+
+//MUST define the current used format as the first item
+static struct rk_sensor_datafmt sensor_colour_fmts[] = {
+	{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}
+};
+//static struct soc_camera_ops sensor_ops;
+
+/*
+**********************************************************
+* Following is local code:
+*
+* Please codeing your program here
+**********************************************************
+*/
+static int sensor_parameter_record(struct i2c_client *client)
+{
+	DBG("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_ae_transfer(struct i2c_client *client)
+{
+	DBG("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+static void dm5150_reinit_parameter(v4l2_std_id std,
+				     struct generic_sensor *sensor)
+{
+	struct rk_sensor_sequence *series = sensor->info_priv.sensor_series;
+	int num_series = sensor->info_priv.num_series;
+	int i;
+
+	switch (std) {
+	case V4L2_STD_NTSC:
+	case V4L2_STD_NTSC_443:
+		SENSOR_PREVIEW_W = 720;
+		SENSOR_PREVIEW_H = 480;
+		sensor->info_priv.dev_sig_cnf.type = RK_CAMERA_DEVICE_CVBS_NTSC;
+		sensor->info_priv.dev_sig_cnf.code =V4L2_MBUS_FMT_UYVY8_2X8;		
+		strcpy(input_mode, "NTSC");
+		break;
+	case V4L2_STD_PAL:
+	case V4L2_STD_PAL_M:
+	case V4L2_STD_PAL_60:
+		SENSOR_PREVIEW_W = 720;
+		SENSOR_PREVIEW_H = 576;
+		sensor->info_priv.dev_sig_cnf.type = RK_CAMERA_DEVICE_CVBS_PAL;
+		sensor->info_priv.dev_sig_cnf.code =V4L2_MBUS_FMT_UYVY8_2X8;
+		strcpy(input_mode, "PAL");
+		break;
+	default:
+		SENSOR_PREVIEW_W = 720;
+		SENSOR_PREVIEW_H = 576;
+		sensor->info_priv.dev_sig_cnf.type = RK_CAMERA_DEVICE_CVBS_NTSC;
+		sensor->info_priv.dev_sig_cnf.code =V4L2_MBUS_FMT_UYVY8_2X8;
+		strcpy(input_mode, "YUV");
+		break;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(defrects); i++) {
+		if ((defrects[i].width == SENSOR_PREVIEW_W) &&
+		    (defrects[i].height == SENSOR_PREVIEW_H)) {
+			SENSOR_PREVIEW_W = defrects[i].defrect.width;
+			SENSOR_PREVIEW_H = defrects[i].defrect.height;
+
+			printk("=============match %dx%d\n", SENSOR_PREVIEW_W, SENSOR_PREVIEW_H);
+			memcpy(&sensor->info_priv.dev_sig_cnf.crop,&defrects[i].defrect,sizeof(defrects[i].defrect));
+
+			if (!defrects[i].interface) {
+				SENSOR_TR("%s(%d): interface is NULL\n",
+					  __func__, __LINE__);
+				printk("=============continue\n");
+				continue;
+			}
+
+			SENSOR_TR("%s(%d): type 0x%x\n", __func__, __LINE__,sensor->info_priv.dev_sig_cnf.type);
+		}
+	}
+		
+	/*update sensor info_priv*/
+	for (i = 0; i < num_series; i++) {
+		series[i].gSeq_info.w = SENSOR_PREVIEW_W;
+		series[i].gSeq_info.h = SENSOR_PREVIEW_H;
+	}
+	 
+	generic_sensor_get_max_min_res(sensor->info_priv.sensor_series,sensor->info_priv.num_series,&(sensor->info_priv.max_real_res),&(sensor->info_priv.max_res),&(sensor->info_priv.min_res));
+
+	printk("===========max_res.h=%d, max_res.w=%d ,max_real_res.h=%d, max_real_res.w=%d ,\n", sensor->info_priv.max_res.h, sensor->info_priv.max_res.w, sensor->info_priv.max_real_res.h, sensor->info_priv.max_real_res.w );
+}
+
+static void dm5150_send_uevent(struct generic_sensor *sensor)
+{
+	char *event_msg = NULL;
+	char *envp[2];
+	DBG("\n====%s\n",__FUNCTION__);
+
+	event_msg = kasprintf(GFP_KERNEL,
+			      "CVBS_NAME=DM5150 NOW_INPUT_MODE=%s RESOLUTION=%dx%d",
+			      input_mode, SENSOR_PREVIEW_W, SENSOR_PREVIEW_H);
+
+	SENSOR_TR("%s(%d): event_msg: %s\n", __func__, __LINE__, event_msg);
+	envp[0] = event_msg;
+	envp[1] = NULL;
+	kobject_uevent_env(&(sensor->subdev.v4l2_dev->dev->kobj),KOBJ_CHANGE, envp);
+}
+
+static v4l2_std_id dm5150_std_to_v4l2(u8 status1)
+{
+	/* in case V4L2_IN_ST_NO_SIGNAL */
+	if (!status1)
+		return V4L2_STD_UNKNOWN;
+
+	switch (status1 & DM5150_REG_VD_STATUS_MASK) {
+	case DM5150_REG_VD_STATUS_NTSC_M_J:
+		return V4L2_STD_NTSC;
+	case DM5150_REG_VD_STATUS_NTSC_4_43:
+		return V4L2_STD_NTSC_443;
+	case DM5150_REG_VD_STATUS_PAL_B_D_N:
+	case DM5150_REG_VD_STATUS_PAL_NC:
+		return V4L2_STD_PAL;
+	case DM5150_REG_VD_STATUS_PAL_M:
+		return V4L2_STD_PAL_M;
+	case DM5150_REG_VD_STATUS_PAL_60:
+		return V4L2_STD_PAL_60;
+	default:
+		return V4L2_STD_UNKNOWN;
+	}
+}
+
+static u32 dm5150_status_to_v4l2(u8 status1)
+{
+	if (!status1)
+		return V4L2_IN_ST_NO_SIGNAL;
+
+	return 0;
+}
+
+static int dm5150_status(struct i2c_client *client, u32 *status,
+			  v4l2_std_id *std)
+{
+	unsigned char status1 = 0;
+	int ret = 0;
+
+	ret = sensor_read(client, DM5150_REG_VD_STATUS, &status1);
+	if (IS_ERR_VALUE(ret)) {
+		SENSOR_TR("%s(%d): register read failed: 0x%x\n",__func__, __LINE__, DM5150_REG_VD_STATUS);
+		return status1;
+	}
+
+	if (status1 < 0)
+		return status1;
+
+	if (status)
+		*status = dm5150_status_to_v4l2(status1);
+	if (std)
+		*std = dm5150_std_to_v4l2(status1);
+
+	return 0;
+}
+
+#define VIDEO_SIGNAL 1
+#define VIDEO_NOSIGAL 0
+
+static struct i2c_client *mClientSignal;
+
+int dm5150_check_signal(struct i2c_client *client,bool isCheck)
+{
+    int nRet = -EINVAL, i ;
+    unsigned char status;
+    int state = VIDEO_NOSIGAL;
+	struct generic_sensor *sensor;
+	struct rk_sensor_sequence *sensor_series;
+	int series_num;
+
+    if (!client)
+        return nRet;
+
+    sensor = to_generic_sensor(client);
+    sensor_series = sensor->info_priv.sensor_series;
+    series_num = sensor->info_priv.num_series;
+
+    for( i = 0; i < series_num ;i++){
+        if((sensor_series[i].property == SEQUENCE_INIT)&&(sensor_series[i].data[0].reg != SEQCMD_END ))
+            break;
+    }
+
+    nRet = sensor_read(client, DM5150_REG_VD_STATUS, &status);
+    if(IS_ERR_VALUE(nRet)){
+        printk("\n status0 failed = 0x%x\n",status);
+    }
+
+	if(status){
+		state = VIDEO_SIGNAL;
+		sensor->info_priv.video_state = RK_CAM_INPUT_VIDEO_STATE_LOCKED;
+	}
+	else{
+		state = VIDEO_NOSIGAL;
+		sensor->info_priv.video_state = RK_CAM_INPUT_VIDEO_STATE_LOSS;
+	}
+
+    return state;
+}
+
+typedef int (*fn_cselect_t)(int channel);
+typedef unsigned char (*fn_csignal_t)(void);
+
+void register_cselect_fn(fn_cselect_t cselect);
+void register_csignal_fn(fn_csignal_t csignal);
+
+#define CVBS_BACK 5
+static int dm5150_channel_select(int channel)
+{
+    int rval;
+    unsigned char val = 0x8a;
+
+    if (!mClientSignal) {
+		return -1;
+	}
+
+	rval = sensor_read(mClientSignal, DM5150_REG_VD_CTRL, &val);
+	if (IS_ERR_VALUE(rval)) {
+		return -1;
+	}
+
+    if (CVBS_BACK == channel) {
+		val |= 0x8;
+		sensor_preview_data[ARRAY_SIZE(sensor_preview_data)-2].val |= 0x8;
+	} else {
+		val &= ~0x8;
+		sensor_preview_data[ARRAY_SIZE(sensor_preview_data)-2].val &= ~0x8;
+	}
+    rval = sensor_write(mClientSignal, DM5150_REG_VD_CTRL, val);
+
+    return rval;
+}
+
+static unsigned char dm5150_readSignalStatus(void)
+{
+    unsigned char nTemp ;
+
+    nTemp = dm5150_check_signal(mClientSignal,true);
+
+    return nTemp;
+}
+
+/*
+* the function is called in open sensor
+*/
+static int sensor_activate_cb(struct i2c_client *client)
+{
+	struct generic_sensor *sensor = to_generic_sensor(client);
+	v4l2_std_id std;
+
+    mClientSignal = client;
+
+	register_csignal_fn(dm5150_readSignalStatus);
+	register_cselect_fn(dm5150_channel_select);
+
+	std = std_last_g;
+	dm5150_status(client, NULL, &std);
+	dm5150_reinit_parameter(std, sensor);
+	dm5150_send_uevent(sensor);
+	if (std_last_g != std) {
+		pr_info("STD changed 0x%llx -> 0x%llx\n", std_last_g, std);
+		std_last_g = std;
+	}
+			
+ //   sensor->info_priv.video_state = RK_CAM_INPUT_VIDEO_STATE_LOCKED;
+	
+	if (sensor->state_check_work.state_check_wq) {
+		SENSOR_DG("sensor_activate_cb: queue_delayed_work 1000ms\n");
+		printk("sensor_activate_cb: queue_delayed_work 1000ms\n");
+        queue_delayed_work(sensor->state_check_work.state_check_wq,&sensor->state_check_work.work,200);
+	}
+
+	return 0;
+}
+
+/*
+* the function is called in close sensor
+*/
+static int sensor_deactivate_cb(struct i2c_client *client)
+{
+	int ret = 0;
+	struct generic_sensor *sensor = to_generic_sensor(client);
+
+	ret = cancel_delayed_work_sync(&sensor->state_check_work.work);
+	return ret;
+}
+/*
+* the function is called before sensor register setting in VIDIOC_S_FMT
+*/
+static int sensor_s_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture)
+{
+    if (capture) {
+        sensor_parameter_record(client);
+    }
+
+    return 0;
+}
+/*
+* the function is called after sensor register setting finished in VIDIOC_S_FMT
+*/
+static int sensor_s_fmt_cb_bh (struct i2c_client *client,struct v4l2_mbus_framefmt *mf, bool capture)
+{
+	printk("%s, fmt.width=%u, fmt.height=%u, code=%u, field=%u, colorspace=%u\n", __FUNCTION__,  mf->width, mf->height, mf->code, mf->field, mf->colorspace);
+
+    if (capture) {
+        sensor_ae_transfer(client);
+    }
+    return 0;
+}
+static int sensor_try_fmt_cb_th(struct i2c_client *client,struct v4l2_mbus_framefmt *mf)
+{
+	return 0;
+}
+
+static int sensor_softrest_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series)
+{
+	return 0;
+}
+static int sensor_check_id_usr_cb(struct i2c_client *client,struct rk_sensor_reg *series)
+{
+	return 0;
+}
+
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+	//struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+	if (pm_msg.event == PM_EVENT_SUSPEND) {
+		DBG("Suspend\n");
+
+	} else {
+		SENSOR_TR("pm_msg.event(0x%x) != PM_EVENT_SUSPEND\n",pm_msg.event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+	printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+static int sensor_mirror_cb (struct i2c_client *client, int mirror)
+{
+
+	return 0;
+}
+/*
+* the function is v4l2 control V4L2_CID_HFLIP callback
+*/
+static int sensor_v4l2ctrl_mirror_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info,
+                                                     struct v4l2_ext_control *ext_ctrl)
+{
+
+	return 0;
+}
+
+static int sensor_flip_cb(struct i2c_client *client, int flip)
+{
+
+	return 0;
+}
+/*
+* the function is v4l2 control V4L2_CID_VFLIP callback
+*/
+static int sensor_v4l2ctrl_flip_cb(struct soc_camera_device *icd, struct sensor_v4l2ctrl_info_s *ctrl_info,
+                                                     struct v4l2_ext_control *ext_ctrl)
+{
+	return 0;
+}
+/*
+* the functions are focus callbacks
+*/
+static int sensor_focus_init_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_single_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_near_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_far_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_specialpos_usr_cb(struct i2c_client *client,int pos){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_const_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+static int sensor_focus_af_const_pause_usr_cb(struct i2c_client *client)
+{
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+static int sensor_focus_af_close_usr_cb(struct i2c_client *client){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+static int sensor_focus_af_zoneupdate_usr_cb(struct i2c_client *client, int *zone_tm_pos)
+{
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+/*
+face defect call back
+*/
+static int 	sensor_face_detect_usr_cb(struct i2c_client *client,int on){
+    printk("\n====%s\n",__FUNCTION__);
+
+	return 0;
+}
+
+/*
+*   The function can been run in sensor_init_parametres which run in sensor_probe, so user can do some
+* initialization in the function.
+*/
+static void dm5150_check_signal_work(struct work_struct *work)
+{
+	struct rk_state_check_work *state_check_work =
+		container_of(work, struct rk_state_check_work, work.work);
+	struct generic_sensor *sensor =
+		container_of(state_check_work,
+			     struct generic_sensor,
+			     state_check_work);
+	struct i2c_client *client = sensor->client;
+	v4l2_std_id std;
+
+	if ((sensor->info_priv.dev_sig_cnf.type ==
+	     RK_CAMERA_DEVICE_BT601_8))
+		return;
+
+	dm5150_status(client, NULL, &std);
+	if (std_last_g != std) {
+		dm5150_reinit_parameter(std, sensor);
+		dm5150_send_uevent(sensor);
+		std_last_g = std;
+		SENSOR_TR("%s(%d):now mode %s\n",
+			  __func__, __LINE__, input_mode);
+	}
+	
+	queue_delayed_work(sensor->state_check_work.state_check_wq,
+			   &sensor->state_check_work.work, 300);
+	
+
+}
+static void sensor_init_parameters_user(struct specific_sensor* spsensor,struct soc_camera_device *icd)
+{
+	/* init work_queue for state_check */
+	INIT_DELAYED_WORK(&spsensor->common_sensor.state_check_work.work,
+			  dm5150_check_signal_work);
+	spsensor->common_sensor.state_check_work.state_check_wq =
+		create_singlethread_workqueue(SENSOR_NAME_STRING(_state_check_workqueue));
+	if (spsensor->common_sensor.state_check_work.state_check_wq == NULL) {
+		SENSOR_TR("%s(%d): %s create failed.\n", __func__, __LINE__,
+			  SENSOR_NAME_STRING(_state_check_workqueue));
+		BUG();
+	}
+
+	memcpy(&spsensor->common_sensor.info_priv.dev_sig_cnf,
+	       &dev_info[0], sizeof(dev_info));
+	spsensor->common_sensor.crop_percent = 0;
+	spsensor->common_sensor.channel_id = 0;
+}
+
+/*
+**It is not allowed to modify the following code
+*/
+sensor_init_parameters_default_code();
+
+sensor_v4l2_struct_initialization();
+
+sensor_probe_default_code();
+
+sensor_remove_default_code();
+
+sensor_driver_default_module_code();

目录arch/arm/mach-rk30/board-rk3168-tb-camera.c

@@ -43,6 +43,15 @@ static struct rkcamera_platform_data new_camera[] = {
                         3,
                         0),
 #else
+#ifdef CONFIG_SOC_CAMERA_DM5150
+    new_camera_device(RK29_CAM_SENSOR_DM5150,
+                        back,
+                        RK30_PIN0_PA6,
+                        0,
+                        3,//bit0:0 1 bit1:0 1 default:0
+                        3,
+                        0),
+#endif
发布了270 篇原创文章 · 获赞 95 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/104450999