brintos

brintos / linux-shallow public Read only

0
0
Text · 16.4 KiB · 25a31a6 Raw
642 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * adv7183.c Analog Devices ADV7183 video decoder driver4 *5 * Copyright (c) 2011 Analog Devices Inc.6 */7 8#include <linux/delay.h>9#include <linux/errno.h>10#include <linux/gpio/consumer.h>11#include <linux/i2c.h>12#include <linux/init.h>13#include <linux/module.h>14#include <linux/slab.h>15#include <linux/types.h>16#include <linux/videodev2.h>17 18#include <media/i2c/adv7183.h>19#include <media/v4l2-ctrls.h>20#include <media/v4l2-device.h>21 22#include "adv7183_regs.h"23 24struct adv7183 {25	struct v4l2_subdev sd;26	struct v4l2_ctrl_handler hdl;27 28	v4l2_std_id std; /* Current set standard */29	u32 input;30	u32 output;31	struct gpio_desc *reset_pin;32	struct gpio_desc *oe_pin;33	struct v4l2_mbus_framefmt fmt;34};35 36/* EXAMPLES USING 27 MHz CLOCK37 * Mode 1 CVBS Input (Composite Video on AIN5)38 * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8.39 */40static const unsigned char adv7183_init_regs[] = {41	ADV7183_IN_CTRL, 0x04,           /* CVBS input on AIN5 */42	ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */43	ADV7183_SHAP_FILT_CTRL, 0x41,    /* Set CSFM to SH1 */44	ADV7183_ADC_CTRL, 0x16,          /* Power down ADC 1 and ADC 2 */45	ADV7183_CTI_DNR_CTRL_4, 0x04,    /* Set DNR threshold to 4 for flat response */46	/* ADI recommended programming sequence */47	ADV7183_ADI_CTRL, 0x80,48	ADV7183_CTI_DNR_CTRL_4, 0x20,49	0x52, 0x18,50	0x58, 0xED,51	0x77, 0xC5,52	0x7C, 0x93,53	0x7D, 0x00,54	0xD0, 0x48,55	0xD5, 0xA0,56	0xD7, 0xEA,57	ADV7183_SD_SATURATION_CR, 0x3E,58	ADV7183_PAL_V_END, 0x3E,59	ADV7183_PAL_F_TOGGLE, 0x0F,60	ADV7183_ADI_CTRL, 0x00,61};62 63static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd)64{65	return container_of(sd, struct adv7183, sd);66}67static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)68{69	return &container_of(ctrl->handler, struct adv7183, hdl)->sd;70}71 72static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg)73{74	struct i2c_client *client = v4l2_get_subdevdata(sd);75 76	return i2c_smbus_read_byte_data(client, reg);77}78 79static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg,80				unsigned char value)81{82	struct i2c_client *client = v4l2_get_subdevdata(sd);83 84	return i2c_smbus_write_byte_data(client, reg, value);85}86 87static int adv7183_writeregs(struct v4l2_subdev *sd,88		const unsigned char *regs, unsigned int num)89{90	unsigned char reg, data;91	unsigned int cnt = 0;92 93	if (num & 0x1) {94		v4l2_err(sd, "invalid regs array\n");95		return -1;96	}97 98	while (cnt < num) {99		reg = *regs++;100		data = *regs++;101		cnt += 2;102 103		adv7183_write(sd, reg, data);104	}105	return 0;106}107 108static int adv7183_log_status(struct v4l2_subdev *sd)109{110	struct adv7183 *decoder = to_adv7183(sd);111 112	v4l2_info(sd, "adv7183: Input control = 0x%02x\n",113			adv7183_read(sd, ADV7183_IN_CTRL));114	v4l2_info(sd, "adv7183: Video selection = 0x%02x\n",115			adv7183_read(sd, ADV7183_VD_SEL));116	v4l2_info(sd, "adv7183: Output control = 0x%02x\n",117			adv7183_read(sd, ADV7183_OUT_CTRL));118	v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n",119			adv7183_read(sd, ADV7183_EXT_OUT_CTRL));120	v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n",121			adv7183_read(sd, ADV7183_AUTO_DET_EN));122	v4l2_info(sd, "adv7183: Contrast = 0x%02x\n",123			adv7183_read(sd, ADV7183_CONTRAST));124	v4l2_info(sd, "adv7183: Brightness = 0x%02x\n",125			adv7183_read(sd, ADV7183_BRIGHTNESS));126	v4l2_info(sd, "adv7183: Hue = 0x%02x\n",127			adv7183_read(sd, ADV7183_HUE));128	v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n",129			adv7183_read(sd, ADV7183_DEF_Y));130	v4l2_info(sd, "adv7183: Default value C = 0x%02x\n",131			adv7183_read(sd, ADV7183_DEF_C));132	v4l2_info(sd, "adv7183: ADI control = 0x%02x\n",133			adv7183_read(sd, ADV7183_ADI_CTRL));134	v4l2_info(sd, "adv7183: Power Management = 0x%02x\n",135			adv7183_read(sd, ADV7183_POW_MANAGE));136	v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",137			adv7183_read(sd, ADV7183_STATUS_1),138			adv7183_read(sd, ADV7183_STATUS_2),139			adv7183_read(sd, ADV7183_STATUS_3));140	v4l2_info(sd, "adv7183: Ident = 0x%02x\n",141			adv7183_read(sd, ADV7183_IDENT));142	v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n",143			adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL));144	v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n",145			adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1));146	v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n",147			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL),148			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2));149	v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n",150			adv7183_read(sd, ADV7183_COMB_FILT_CTRL));151	v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n",152			adv7183_read(sd, ADV7183_ADI_CTRL_2));153	v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n",154			adv7183_read(sd, ADV7183_PIX_DELAY_CTRL));155	v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n",156			adv7183_read(sd, ADV7183_MISC_GAIN_CTRL));157	v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n",158			adv7183_read(sd, ADV7183_AGC_MODE_CTRL));159	v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n",160			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1),161			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2));162	v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n",163			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1),164			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2));165	v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",166			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1),167			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2),168			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3));169	v4l2_info(sd, "adv7183: Hsync position control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",170			adv7183_read(sd, ADV7183_HS_POS_CTRL_1),171			adv7183_read(sd, ADV7183_HS_POS_CTRL_2),172			adv7183_read(sd, ADV7183_HS_POS_CTRL_3));173	v4l2_info(sd, "adv7183: Polarity = 0x%02x\n",174			adv7183_read(sd, ADV7183_POLARITY));175	v4l2_info(sd, "adv7183: ADC control = 0x%02x\n",176			adv7183_read(sd, ADV7183_ADC_CTRL));177	v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n",178			adv7183_read(sd, ADV7183_SD_OFFSET_CB),179			adv7183_read(sd, ADV7183_SD_OFFSET_CR));180	v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n",181			adv7183_read(sd, ADV7183_SD_SATURATION_CB),182			adv7183_read(sd, ADV7183_SD_SATURATION_CR));183	v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n",184			adv7183_read(sd, ADV7183_DRIVE_STR));185	v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name);186	return 0;187}188 189static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)190{191	struct adv7183 *decoder = to_adv7183(sd);192 193	*std = decoder->std;194	return 0;195}196 197static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std)198{199	struct adv7183 *decoder = to_adv7183(sd);200	int reg;201 202	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;203	if (std == V4L2_STD_PAL_60)204		reg |= 0x60;205	else if (std == V4L2_STD_NTSC_443)206		reg |= 0x70;207	else if (std == V4L2_STD_PAL_N)208		reg |= 0x90;209	else if (std == V4L2_STD_PAL_M)210		reg |= 0xA0;211	else if (std == V4L2_STD_PAL_Nc)212		reg |= 0xC0;213	else if (std & V4L2_STD_PAL)214		reg |= 0x80;215	else if (std & V4L2_STD_NTSC)216		reg |= 0x50;217	else if (std & V4L2_STD_SECAM)218		reg |= 0xE0;219	else220		return -EINVAL;221	adv7183_write(sd, ADV7183_IN_CTRL, reg);222 223	decoder->std = std;224 225	return 0;226}227 228static int adv7183_reset(struct v4l2_subdev *sd, u32 val)229{230	int reg;231 232	reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80;233	adv7183_write(sd, ADV7183_POW_MANAGE, reg);234	/* wait 5ms before any further i2c writes are performed */235	usleep_range(5000, 10000);236	return 0;237}238 239static int adv7183_s_routing(struct v4l2_subdev *sd,240				u32 input, u32 output, u32 config)241{242	struct adv7183 *decoder = to_adv7183(sd);243	int reg;244 245	if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT))246		return -EINVAL;247 248	if (input != decoder->input) {249		decoder->input = input;250		reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0;251		switch (input) {252		case ADV7183_COMPOSITE1:253			reg |= 0x1;254			break;255		case ADV7183_COMPOSITE2:256			reg |= 0x2;257			break;258		case ADV7183_COMPOSITE3:259			reg |= 0x3;260			break;261		case ADV7183_COMPOSITE4:262			reg |= 0x4;263			break;264		case ADV7183_COMPOSITE5:265			reg |= 0x5;266			break;267		case ADV7183_COMPOSITE6:268			reg |= 0xB;269			break;270		case ADV7183_COMPOSITE7:271			reg |= 0xC;272			break;273		case ADV7183_COMPOSITE8:274			reg |= 0xD;275			break;276		case ADV7183_COMPOSITE9:277			reg |= 0xE;278			break;279		case ADV7183_COMPOSITE10:280			reg |= 0xF;281			break;282		case ADV7183_SVIDEO0:283			reg |= 0x6;284			break;285		case ADV7183_SVIDEO1:286			reg |= 0x7;287			break;288		case ADV7183_SVIDEO2:289			reg |= 0x8;290			break;291		case ADV7183_COMPONENT0:292			reg |= 0x9;293			break;294		case ADV7183_COMPONENT1:295			reg |= 0xA;296			break;297		default:298			break;299		}300		adv7183_write(sd, ADV7183_IN_CTRL, reg);301	}302 303	if (output != decoder->output) {304		decoder->output = output;305		reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0;306		switch (output) {307		case ADV7183_16BIT_OUT:308			reg |= 0x9;309			break;310		default:311			reg |= 0xC;312			break;313		}314		adv7183_write(sd, ADV7183_OUT_CTRL, reg);315	}316 317	return 0;318}319 320static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl)321{322	struct v4l2_subdev *sd = to_sd(ctrl);323	int val = ctrl->val;324 325	switch (ctrl->id) {326	case V4L2_CID_BRIGHTNESS:327		if (val < 0)328			val = 127 - val;329		adv7183_write(sd, ADV7183_BRIGHTNESS, val);330		break;331	case V4L2_CID_CONTRAST:332		adv7183_write(sd, ADV7183_CONTRAST, val);333		break;334	case V4L2_CID_SATURATION:335		adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8);336		adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF));337		break;338	case V4L2_CID_HUE:339		adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8);340		adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF));341		break;342	default:343		return -EINVAL;344	}345 346	return 0;347}348 349static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)350{351	struct adv7183 *decoder = to_adv7183(sd);352	int reg;353 354	/* enable autodetection block */355	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;356	adv7183_write(sd, ADV7183_IN_CTRL, reg);357 358	/* wait autodetection switch */359	mdelay(10);360 361	/* get autodetection result */362	reg = adv7183_read(sd, ADV7183_STATUS_1);363	switch ((reg >> 0x4) & 0x7) {364	case 0:365		*std &= V4L2_STD_NTSC;366		break;367	case 1:368		*std &= V4L2_STD_NTSC_443;369		break;370	case 2:371		*std &= V4L2_STD_PAL_M;372		break;373	case 3:374		*std &= V4L2_STD_PAL_60;375		break;376	case 4:377		*std &= V4L2_STD_PAL;378		break;379	case 5:380		*std &= V4L2_STD_SECAM;381		break;382	case 6:383		*std &= V4L2_STD_PAL_Nc;384		break;385	case 7:386		*std &= V4L2_STD_SECAM;387		break;388	default:389		*std = V4L2_STD_UNKNOWN;390		break;391	}392 393	/* after std detection, write back user set std */394	adv7183_s_std(sd, decoder->std);395	return 0;396}397 398static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status)399{400	int reg;401 402	*status = V4L2_IN_ST_NO_SIGNAL;403	reg = adv7183_read(sd, ADV7183_STATUS_1);404	if (reg < 0)405		return reg;406	if (reg & 0x1)407		*status = 0;408	return 0;409}410 411static int adv7183_enum_mbus_code(struct v4l2_subdev *sd,412		struct v4l2_subdev_state *sd_state,413		struct v4l2_subdev_mbus_code_enum *code)414{415	if (code->pad || code->index > 0)416		return -EINVAL;417 418	code->code = MEDIA_BUS_FMT_UYVY8_2X8;419	return 0;420}421 422static int adv7183_set_fmt(struct v4l2_subdev *sd,423		struct v4l2_subdev_state *sd_state,424		struct v4l2_subdev_format *format)425{426	struct adv7183 *decoder = to_adv7183(sd);427	struct v4l2_mbus_framefmt *fmt = &format->format;428 429	if (format->pad)430		return -EINVAL;431 432	fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;433	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;434	if (decoder->std & V4L2_STD_525_60) {435		fmt->field = V4L2_FIELD_SEQ_TB;436		fmt->width = 720;437		fmt->height = 480;438	} else {439		fmt->field = V4L2_FIELD_SEQ_BT;440		fmt->width = 720;441		fmt->height = 576;442	}443	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)444		decoder->fmt = *fmt;445	return 0;446}447 448static int adv7183_get_fmt(struct v4l2_subdev *sd,449		struct v4l2_subdev_state *sd_state,450		struct v4l2_subdev_format *format)451{452	struct adv7183 *decoder = to_adv7183(sd);453 454	if (format->pad)455		return -EINVAL;456 457	format->format = decoder->fmt;458	return 0;459}460 461static int adv7183_s_stream(struct v4l2_subdev *sd, int enable)462{463	struct adv7183 *decoder = to_adv7183(sd);464 465	if (enable)466		gpiod_set_value(decoder->oe_pin, 1);467	else468		gpiod_set_value(decoder->oe_pin, 0);469	udelay(1);470	return 0;471}472 473#ifdef CONFIG_VIDEO_ADV_DEBUG474static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)475{476	reg->val = adv7183_read(sd, reg->reg & 0xff);477	reg->size = 1;478	return 0;479}480 481static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)482{483	adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff);484	return 0;485}486#endif487 488static const struct v4l2_ctrl_ops adv7183_ctrl_ops = {489	.s_ctrl = adv7183_s_ctrl,490};491 492static const struct v4l2_subdev_core_ops adv7183_core_ops = {493	.log_status = adv7183_log_status,494	.reset = adv7183_reset,495#ifdef CONFIG_VIDEO_ADV_DEBUG496	.g_register = adv7183_g_register,497	.s_register = adv7183_s_register,498#endif499};500 501static const struct v4l2_subdev_video_ops adv7183_video_ops = {502	.g_std = adv7183_g_std,503	.s_std = adv7183_s_std,504	.s_routing = adv7183_s_routing,505	.querystd = adv7183_querystd,506	.g_input_status = adv7183_g_input_status,507	.s_stream = adv7183_s_stream,508};509 510static const struct v4l2_subdev_pad_ops adv7183_pad_ops = {511	.enum_mbus_code = adv7183_enum_mbus_code,512	.get_fmt = adv7183_get_fmt,513	.set_fmt = adv7183_set_fmt,514};515 516static const struct v4l2_subdev_ops adv7183_ops = {517	.core = &adv7183_core_ops,518	.video = &adv7183_video_ops,519	.pad = &adv7183_pad_ops,520};521 522static int adv7183_probe(struct i2c_client *client)523{524	struct adv7183 *decoder;525	struct v4l2_subdev *sd;526	struct v4l2_ctrl_handler *hdl;527	int ret;528	struct v4l2_subdev_format fmt = {529		.which = V4L2_SUBDEV_FORMAT_ACTIVE,530	};531 532	/* Check if the adapter supports the needed features */533	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))534		return -EIO;535 536	v4l_info(client, "chip found @ 0x%02x (%s)\n",537			client->addr << 1, client->adapter->name);538 539	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);540	if (decoder == NULL)541		return -ENOMEM;542 543	/*544	 * Requesting high will assert reset, the line should be545	 * flagged as active low in descriptor table or machine description.546	 */547	decoder->reset_pin = devm_gpiod_get(&client->dev, "reset",548					    GPIOD_OUT_HIGH);549	if (IS_ERR(decoder->reset_pin))550		return PTR_ERR(decoder->reset_pin);551	gpiod_set_consumer_name(decoder->reset_pin, "ADV7183 Reset");552	/*553	 * Requesting low will start with output disabled, the line should be554	 * flagged as active low in descriptor table or machine description.555	 */556	decoder->oe_pin = devm_gpiod_get(&client->dev, "oe",557					 GPIOD_OUT_LOW);558	if (IS_ERR(decoder->oe_pin))559		return PTR_ERR(decoder->oe_pin);560	gpiod_set_consumer_name(decoder->reset_pin, "ADV7183 Output Enable");561 562	sd = &decoder->sd;563	v4l2_i2c_subdev_init(sd, client, &adv7183_ops);564 565	hdl = &decoder->hdl;566	v4l2_ctrl_handler_init(hdl, 4);567	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,568			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);569	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,570			V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80);571	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,572			V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080);573	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,574			V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080);575	/* hook the control handler into the driver */576	sd->ctrl_handler = hdl;577	if (hdl->error) {578		ret = hdl->error;579 580		v4l2_ctrl_handler_free(hdl);581		return ret;582	}583 584	/* v4l2 doesn't support an autodetect standard, pick PAL as default */585	decoder->std = V4L2_STD_PAL;586	decoder->input = ADV7183_COMPOSITE4;587	decoder->output = ADV7183_8BIT_OUT;588 589	/* reset chip */590	/* reset pulse width at least 5ms */591	mdelay(10);592	/* De-assert reset line (descriptor tagged active low) */593	gpiod_set_value(decoder->reset_pin, 0);594	/* wait 5ms before any further i2c writes are performed */595	mdelay(5);596 597	adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs));598	adv7183_s_std(sd, decoder->std);599	fmt.format.width = 720;600	fmt.format.height = 576;601	adv7183_set_fmt(sd, NULL, &fmt);602 603	/* initialize the hardware to the default control values */604	ret = v4l2_ctrl_handler_setup(hdl);605	if (ret) {606		v4l2_ctrl_handler_free(hdl);607		return ret;608	}609 610	return 0;611}612 613static void adv7183_remove(struct i2c_client *client)614{615	struct v4l2_subdev *sd = i2c_get_clientdata(client);616 617	v4l2_device_unregister_subdev(sd);618	v4l2_ctrl_handler_free(sd->ctrl_handler);619}620 621static const struct i2c_device_id adv7183_id[] = {622	{ "adv7183" },623	{}624};625 626MODULE_DEVICE_TABLE(i2c, adv7183_id);627 628static struct i2c_driver adv7183_driver = {629	.driver = {630		.name   = "adv7183",631	},632	.probe          = adv7183_probe,633	.remove         = adv7183_remove,634	.id_table       = adv7183_id,635};636 637module_i2c_driver(adv7183_driver);638 639MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");640MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");641MODULE_LICENSE("GPL v2");642