16789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors/* 26789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * adv7180.c Analog Devices ADV7180 video decoder driver 36789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * Copyright (c) 2009 Intel Corporation 4cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov * Copyright (C) 2013 Cogent Embedded, Inc. 5cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov * Copyright (C) 2013 Renesas Solutions Corp. 66789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * 76789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * This program is free software; you can redistribute it and/or modify 86789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * it under the terms of the GNU General Public License version 2 as 96789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * published by the Free Software Foundation. 106789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * 116789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * This program is distributed in the hope that it will be useful, 126789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of 136789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 146789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * GNU General Public License for more details. 156789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * 166789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * You should have received a copy of the GNU General Public License 176789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * along with this program; if not, write to the Free Software 186789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 196789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors */ 206789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 216789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/module.h> 226789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/init.h> 236789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/errno.h> 246789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/kernel.h> 256789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/interrupt.h> 266789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/i2c.h> 275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 286789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <media/v4l2-ioctl.h> 296789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <linux/videodev2.h> 306789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#include <media/v4l2-device.h> 31c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#include <media/v4l2-ctrls.h> 3242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#include <linux/mutex.h> 336789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 34d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_REG 0x00 35d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 36d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 37d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM 0x20 38d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM 0x30 39d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_NTSC_J 0x40 40d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_NTSC_M 0x50 41d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL60 0x60 42d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_NTSC_443 0x70 43d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_BG 0x80 44d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_N 0x90 45d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_M 0xa0 46d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_M_PED 0xb0 47d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_COMB_N 0xc0 48d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0 49d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0 50d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0 51bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_INPUT_CONTROL_INSEL_MASK 0x0f 52d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 5342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG 0x04 5442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5 556789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 5642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_AUTODETECT_ENABLE_REG 0x07 5742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_AUTODETECT_DEFAULT 0x7f 58c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga/* Contrast */ 59bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_CON_REG 0x08 /*Unsigned */ 60c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_CON_MIN 0 61c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_CON_DEF 128 62c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_CON_MAX 255 63c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga/* Brightness*/ 64bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_BRI_REG 0x0a /*Signed */ 65c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_BRI_MIN -128 66c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_BRI_DEF 0 67c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_BRI_MAX 127 68c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga/* Hue */ 69bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_HUE_REG 0x0b /*Signed, inverted */ 70c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_HUE_MIN -127 71c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_HUE_DEF 0 72c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_HUE_MAX 128 73bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 7442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ADI_CTRL_REG 0x0e 7542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 766789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 77bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_PWR_MAN_REG 0x0f 78bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_PWR_MAN_ON 0x04 79bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_PWR_MAN_OFF 0x24 80bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_PWR_MAN_RES 0x80 81bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 82d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_STATUS1_REG 0x10 83d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_STATUS1_IN_LOCK 0x01 84d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors#define ADV7180_STATUS1_AUTOD_MASK 0x70 856789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_NTSM_M_J 0x00 866789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10 876789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_PAL_M 0x20 886789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_PAL_60 0x30 896789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_PAL_B_G 0x40 906789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_SECAM 0x50 916789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_PAL_COMB 0x60 926789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_STATUS1_AUTOD_SECAM_525 0x70 936789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 946789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_IDENT_REG 0x11 956789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors#define ADV7180_ID_7180 0x18 966789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 9742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICONF1_ADI 0x40 9842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICONF1_ACTIVE_LOW 0x01 9942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICONF1_PSYNC_ONLY 0x10 10042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 101c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga/* Saturation */ 102bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_SD_SAT_CB_REG 0xe3 /*Unsigned */ 103bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_SD_SAT_CR_REG 0xe4 /*Unsigned */ 104c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_SAT_MIN 0 105c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_SAT_DEF 128 106c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define ADV7180_SAT_MAX 255 107bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 10842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IRQ1_LOCK 0x01 10942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IRQ1_UNLOCK 0x02 11042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ISR1_ADI 0x42 11142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICR1_ADI 0x43 11242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IMR1_ADI 0x44 11342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IMR2_ADI 0x48 11442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IRQ3_AD_CHANGE 0x08 11542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ISR3_ADI 0x4A 11642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_ICR3_ADI 0x4B 11742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IMR3_ADI 0x4C 11842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors#define ADV7180_IMR4_ADI 0x50 1196789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 120bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_NTSC_V_BIT_END_REG 0xE6 121bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F 122bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 1236789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstruct adv7180_state { 124c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga struct v4l2_ctrl_handler ctrl_hdl; 125c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors struct v4l2_subdev sd; 12642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors struct mutex mutex; /* mutual excl. when accessing chip */ 12742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors int irq; 128c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors v4l2_std_id curr_norm; 129c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors bool autodetect; 130e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen bool powered; 131bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga u8 input; 1326789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 133c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ 134c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga struct adv7180_state, \ 135c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ctrl_hdl)->sd) 1366789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 137d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjforsstatic v4l2_std_id adv7180_std_to_v4l2(u8 status1) 1386789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors{ 139b294a1921454fbcc6e983750ae977ce8a28f31bcVladimir Barinov /* in case V4L2_IN_ST_NO_SIGNAL */ 140b294a1921454fbcc6e983750ae977ce8a28f31bcVladimir Barinov if (!(status1 & ADV7180_STATUS1_IN_LOCK)) 141b294a1921454fbcc6e983750ae977ce8a28f31bcVladimir Barinov return V4L2_STD_UNKNOWN; 142b294a1921454fbcc6e983750ae977ce8a28f31bcVladimir Barinov 1436789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors switch (status1 & ADV7180_STATUS1_AUTOD_MASK) { 1446789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_NTSM_M_J: 145d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors return V4L2_STD_NTSC; 1466789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_NTSC_4_43: 1476789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_NTSC_443; 1486789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_PAL_M: 1496789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_PAL_M; 1506789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_PAL_60: 1516789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_PAL_60; 1526789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_PAL_B_G: 1536789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_PAL; 1546789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_SECAM: 1556789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_SECAM; 1566789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_PAL_COMB: 1576789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N; 1586789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors case ADV7180_STATUS1_AUTOD_SECAM_525: 1596789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_SECAM; 1606789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors default: 1616789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return V4L2_STD_UNKNOWN; 1626789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors } 1636789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors} 1646789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 165c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjforsstatic int v4l2_std_to_adv7180(v4l2_std_id std) 166c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors{ 167c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_PAL_60) 168c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL60; 169c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_NTSC_443) 170c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_NTSC_443; 171c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_PAL_N) 172c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL_N; 173c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_PAL_M) 174c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL_M; 175c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_PAL_Nc) 176c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL_COMB_N; 177c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 178c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std & V4L2_STD_PAL) 179c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL_BG; 180c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std & V4L2_STD_NTSC) 181c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_NTSC_M; 182c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std & V4L2_STD_SECAM) 183c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ADV7180_INPUT_CONTROL_PAL_SECAM; 184c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 185c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return -EINVAL; 186c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors} 187c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 188d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjforsstatic u32 adv7180_status_to_v4l2(u8 status1) 189d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors{ 190d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors if (!(status1 & ADV7180_STATUS1_IN_LOCK)) 191d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors return V4L2_IN_ST_NO_SIGNAL; 192d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 193d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors return 0; 194d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors} 195d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 196d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjforsstatic int __adv7180_status(struct i2c_client *client, u32 *status, 197bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga v4l2_std_id *std) 198d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors{ 199d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG); 200d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 201d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors if (status1 < 0) 202d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors return status1; 203d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 204d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors if (status) 205d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors *status = adv7180_status_to_v4l2(status1); 206d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors if (std) 207d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors *std = adv7180_std_to_v4l2(status1); 208d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 209d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors return 0; 210d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors} 211d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors 2126789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic inline struct adv7180_state *to_state(struct v4l2_subdev *sd) 2136789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors{ 2146789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return container_of(sd, struct adv7180_state, sd); 2156789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors} 2166789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 2176789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) 2186789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors{ 219c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors struct adv7180_state *state = to_state(sd); 22042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors int err = mutex_lock_interruptible(&state->mutex); 22142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (err) 22242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return err; 223c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 22442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* when we are interrupt driven we know the state */ 22542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (!state->autodetect || state->irq > 0) 226c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors *std = state->curr_norm; 227c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors else 228c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std); 229c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 23042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors mutex_unlock(&state->mutex); 231c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return err; 232d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors} 2336789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 234bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vagastatic int adv7180_s_routing(struct v4l2_subdev *sd, u32 input, 235bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga u32 output, u32 config) 236bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga{ 237bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct adv7180_state *state = to_state(sd); 238bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga int ret = mutex_lock_interruptible(&state->mutex); 239bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct i2c_client *client = v4l2_get_subdevdata(sd); 240bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 241bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret) 242bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 243bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 244c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept 245bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga * all inputs and let the card driver take care of validation 246bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga */ 247bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) 248bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga goto out; 249bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 250bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = i2c_smbus_read_byte_data(client, ADV7180_INPUT_CONTROL_REG); 251bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 252bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 253bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga goto out; 254bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 255bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; 256bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = i2c_smbus_write_byte_data(client, 257bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_INPUT_CONTROL_REG, ret | input); 258bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga state->input = input; 259bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vagaout: 260bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga mutex_unlock(&state->mutex); 261bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 262bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga} 263bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 264d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjforsstatic int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) 265d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors{ 26642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors struct adv7180_state *state = to_state(sd); 26742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors int ret = mutex_lock_interruptible(&state->mutex); 26842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret) 26942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return ret; 27042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 27142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL); 27242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors mutex_unlock(&state->mutex); 27342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return ret; 2746789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors} 2756789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 276c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjforsstatic int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 277c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors{ 278c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors struct adv7180_state *state = to_state(sd); 279c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors struct i2c_client *client = v4l2_get_subdevdata(sd); 28042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors int ret = mutex_lock_interruptible(&state->mutex); 28142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret) 28242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return ret; 283c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 284c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors /* all standards -> autodetect */ 285c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (std == V4L2_STD_ALL) { 286bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = 287bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, 288bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 289bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga | state->input); 290c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (ret < 0) 291c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors goto out; 292c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 29342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors __adv7180_status(client, NULL, &state->curr_norm); 294c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors state->autodetect = true; 295c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors } else { 296c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors ret = v4l2_std_to_adv7180(std); 297c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (ret < 0) 298c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors goto out; 299c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 300c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors ret = i2c_smbus_write_byte_data(client, 301bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_INPUT_CONTROL_REG, 302bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret | state->input); 303c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors if (ret < 0) 304c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors goto out; 305c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 306c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors state->curr_norm = std; 307c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors state->autodetect = false; 308c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors } 309c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors ret = 0; 310c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjforsout: 31142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors mutex_unlock(&state->mutex); 312c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors return ret; 313c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors} 314c277b60a08fe9e201656528b3f5cd35b554e24afRichard Röjfors 315e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausenstatic int adv7180_set_power(struct adv7180_state *state, 316e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen struct i2c_client *client, bool on) 317e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen{ 318e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen u8 val; 319e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 320e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen if (on) 321e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen val = ADV7180_PWR_MAN_ON; 322e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen else 323e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen val = ADV7180_PWR_MAN_OFF; 324e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 325e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen return i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, val); 326e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen} 327e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 328e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausenstatic int adv7180_s_power(struct v4l2_subdev *sd, int on) 329e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen{ 330e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen struct adv7180_state *state = to_state(sd); 331e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen struct i2c_client *client = v4l2_get_subdevdata(sd); 332e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen int ret; 333e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 334e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen ret = mutex_lock_interruptible(&state->mutex); 335e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen if (ret) 336e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen return ret; 337e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 338e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen ret = adv7180_set_power(state, client, on); 339e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen if (ret == 0) 340e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen state->powered = on; 341e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 342e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen mutex_unlock(&state->mutex); 343e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen return ret; 344e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen} 345e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen 346c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vagastatic int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) 347bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga{ 348c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga struct v4l2_subdev *sd = to_adv7180_sd(ctrl); 349bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct adv7180_state *state = to_state(sd); 350bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct i2c_client *client = v4l2_get_subdevdata(sd); 351bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga int ret = mutex_lock_interruptible(&state->mutex); 352c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga int val; 353c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 354bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret) 355bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 356c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga val = ctrl->val; 357bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga switch (ctrl->id) { 358bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga case V4L2_CID_BRIGHTNESS: 359c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val); 360bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga break; 361bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga case V4L2_CID_HUE: 362bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga /*Hue is inverted according to HSL chart */ 363c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val); 364bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga break; 365bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga case V4L2_CID_CONTRAST: 366c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val); 367bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga break; 368bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga case V4L2_CID_SATURATION: 369bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga /* 370bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE 371bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga *Let's not confuse the user, everybody understands saturation 372bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga */ 373c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG, 374c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga val); 375bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 376bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga break; 377c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG, 378c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga val); 379bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga break; 380bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga default: 381bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = -EINVAL; 382bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga } 383bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 384bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga mutex_unlock(&state->mutex); 385bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 386bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga} 387bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 388c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vagastatic const struct v4l2_ctrl_ops adv7180_ctrl_ops = { 389c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga .s_ctrl = adv7180_s_ctrl, 390c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga}; 391c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 392c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vagastatic int adv7180_init_controls(struct adv7180_state *state) 393c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga{ 394c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); 395c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 396c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, 397c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN, 398c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF); 399c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, 400c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga V4L2_CID_CONTRAST, ADV7180_CON_MIN, 401c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ADV7180_CON_MAX, 1, ADV7180_CON_DEF); 402c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, 403c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga V4L2_CID_SATURATION, ADV7180_SAT_MIN, 404c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF); 405c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, 406c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga V4L2_CID_HUE, ADV7180_HUE_MIN, 407c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); 408c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga state->sd.ctrl_handler = &state->ctrl_hdl; 409c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga if (state->ctrl_hdl.error) { 410c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga int err = state->ctrl_hdl.error; 411c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 412c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_handler_free(&state->ctrl_hdl); 413c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga return err; 414c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga } 415c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_handler_setup(&state->ctrl_hdl); 416c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 417c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga return 0; 418c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga} 419c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vagastatic void adv7180_exit_controls(struct adv7180_state *state) 420c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga{ 421c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga v4l2_ctrl_handler_free(&state->ctrl_hdl); 422c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga} 423c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga 424cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinovstatic int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, 425cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov enum v4l2_mbus_pixelcode *code) 426cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov{ 427cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov if (index > 0) 428cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov return -EINVAL; 429cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 430cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov *code = V4L2_MBUS_FMT_YUYV8_2X8; 431cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 432cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov return 0; 433cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov} 434cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 435cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinovstatic int adv7180_mbus_fmt(struct v4l2_subdev *sd, 436cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov struct v4l2_mbus_framefmt *fmt) 437cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov{ 438cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov struct adv7180_state *state = to_state(sd); 439cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 440cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; 441cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; 442cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov fmt->field = V4L2_FIELD_INTERLACED; 443cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov fmt->width = 720; 444cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576; 445cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 446cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov return 0; 447cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov} 448cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 449cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinovstatic int adv7180_g_mbus_config(struct v4l2_subdev *sd, 450cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov struct v4l2_mbus_config *cfg) 451cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov{ 452cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov /* 453cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov * The ADV7180 sensor supports BT.601/656 output modes. 454cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov * The BT.656 is default and not yet configurable by s/w. 455cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov */ 456cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | 457cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov V4L2_MBUS_DATA_ACTIVE_HIGH; 458cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov cfg->type = V4L2_MBUS_BT656; 459cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 460cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov return 0; 461cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov} 462cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov 4636789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic const struct v4l2_subdev_video_ops adv7180_video_ops = { 4648774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart .s_std = adv7180_s_std, 4656789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors .querystd = adv7180_querystd, 466d31242943a73aba0e5cfd0ea674b5e694b4a39e6Richard Röjfors .g_input_status = adv7180_g_input_status, 467bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga .s_routing = adv7180_s_routing, 468cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov .enum_mbus_fmt = adv7180_enum_mbus_fmt, 469cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov .try_mbus_fmt = adv7180_mbus_fmt, 470cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov .g_mbus_fmt = adv7180_mbus_fmt, 471cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov .s_mbus_fmt = adv7180_mbus_fmt, 472cccb83f7a1848a8b2dda6480c2dc26e80710e50bVladimir Barinov .g_mbus_config = adv7180_g_mbus_config, 4736789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 4746789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 4756789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic const struct v4l2_subdev_core_ops adv7180_core_ops = { 476e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen .s_power = adv7180_s_power, 4776789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 4786789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 4796789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic const struct v4l2_subdev_ops adv7180_ops = { 4806789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors .core = &adv7180_core_ops, 4816789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors .video = &adv7180_video_ops, 4826789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 4836789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 4840c25534d456535a879aba482dc14795213312514Lars-Peter Clausenstatic irqreturn_t adv7180_irq(int irq, void *devid) 48542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors{ 4860c25534d456535a879aba482dc14795213312514Lars-Peter Clausen struct adv7180_state *state = devid; 48742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors struct i2c_client *client = v4l2_get_subdevdata(&state->sd); 48842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors u8 isr3; 48942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 49042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors mutex_lock(&state->mutex); 49142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 492bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_ADI_CTRL_IRQ_SPACE); 49342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI); 49442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* clear */ 49542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3); 49642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0); 49742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 49842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) 49942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors __adv7180_status(client, NULL, &state->curr_norm); 50042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors mutex_unlock(&state->mutex); 50142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 50242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return IRQ_HANDLED; 50342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors} 50442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 505bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vagastatic int init_device(struct i2c_client *client, struct adv7180_state *state) 5066789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors{ 5076789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors int ret; 5086789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 5096789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors /* Initialize adv7180 */ 51042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* Enable autodetection */ 511bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (state->autodetect) { 512bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = 513bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, 514bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 515bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga | state->input); 516bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 517bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 51842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 519bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = 520bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga i2c_smbus_write_byte_data(client, 521bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_AUTODETECT_ENABLE_REG, 522bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_AUTODETECT_DEFAULT); 523bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 524bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 525bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga } else { 526bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = v4l2_std_to_adv7180(state->curr_norm); 527bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 528bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 52942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 530bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = 531bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG, 532bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret | state->input); 533bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 534bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 535bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 536bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga } 53742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* ITU-R BT.656-4 compatible */ 53842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, 539bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_EXTENDED_OUTPUT_CONTROL_REG, 540bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS); 54142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 542bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 543bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 544bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga /* Manually set V bit end position in NTSC mode */ 545bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = i2c_smbus_write_byte_data(client, 546bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_NTSC_V_BIT_END_REG, 547bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_NTSC_V_BIT_END_MANUAL_NVEND); 548bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 549bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 55042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 55142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* read current norm */ 55242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors __adv7180_status(client, NULL, &state->curr_norm); 55342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 55442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* register for interrupts */ 55542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (state->irq > 0) { 5560c25534d456535a879aba482dc14795213312514Lars-Peter Clausen ret = request_threaded_irq(state->irq, NULL, adv7180_irq, 5570c25534d456535a879aba482dc14795213312514Lars-Peter Clausen IRQF_ONESHOT, KBUILD_MODNAME, state); 55842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret) 559bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 56042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 56142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 562bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_ADI_CTRL_IRQ_SPACE); 56342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 564df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 56542752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 56642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* config the Interrupt pin to be active low */ 56742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI, 568bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_ICONF1_ACTIVE_LOW | 569bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_ICONF1_PSYNC_ONLY); 57042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 571df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 57242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 57342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0); 57442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 575df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 57642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 57742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0); 57842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 579df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 58042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 58142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors /* enable AD change interrupts interrupts */ 58242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI, 583bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ADV7180_IRQ3_AD_CHANGE); 58442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 585df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 58642752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 58742752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0); 58842752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 589df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 59042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 59142752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 592bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 0); 59342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors if (ret < 0) 594df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov goto err; 5956789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors } 5966789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 597bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return 0; 598df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov 599df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshiloverr: 600df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov free_irq(state->irq, state); 601df065b373f882c4efc396afa1f31cd8afedab356Alexey Khoroshilov return ret; 602bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga} 603bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 6044c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartmanstatic int adv7180_probe(struct i2c_client *client, 6054c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartman const struct i2c_device_id *id) 606bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga{ 607bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct adv7180_state *state; 608bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct v4l2_subdev *sd; 609bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga int ret; 610bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 611bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga /* Check if the adapter supports the needed features */ 612bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 613bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return -EIO; 614bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 615bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga v4l_info(client, "chip found @ 0x%02x (%s)\n", 616bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga client->addr, client->adapter->name); 617bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 618c02b211df6fc54e51ee554c27a6736a11255a764Laurent Pinchart state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); 619bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (state == NULL) { 620bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = -ENOMEM; 621bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga goto err; 622bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga } 623bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 624bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga state->irq = client->irq; 625bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga mutex_init(&state->mutex); 626bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga state->autodetect = true; 627e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen state->powered = true; 628bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga state->input = 0; 629bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga sd = &state->sd; 630bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga v4l2_i2c_subdev_init(sd, client, &adv7180_ops); 631bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 632c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = adv7180_init_controls(state); 633c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga if (ret) 634bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga goto err_unreg_subdev; 635c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga ret = init_device(client, state); 636c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga if (ret) 637c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga goto err_free_ctrl; 638fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen 639fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen ret = v4l2_async_register_subdev(sd); 640fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen if (ret) 641fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen goto err_free_irq; 642fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen 6436789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return 0; 64442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 645fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausenerr_free_irq: 646fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen if (state->irq > 0) 647fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen free_irq(client->irq, state); 648c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vagaerr_free_ctrl: 649c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga adv7180_exit_controls(state); 65042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjforserr_unreg_subdev: 651297a0ae32bf84c8ae135971eb21f18ee5f4ca3eaLars-Peter Clausen mutex_destroy(&state->mutex); 65242752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjforserr: 65342752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors return ret; 6546789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors} 6556789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 6564c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartmanstatic int adv7180_remove(struct i2c_client *client) 6576789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors{ 6586789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors struct v4l2_subdev *sd = i2c_get_clientdata(client); 65942752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors struct adv7180_state *state = to_state(sd); 66042752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors 661fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen v4l2_async_unregister_subdev(sd); 662fa5b7945aefdbcd4419f0b8872ce67866d8071e3Lars-Peter Clausen 6630c25534d456535a879aba482dc14795213312514Lars-Peter Clausen if (state->irq > 0) 66442752f7a3f4afbabb513d5769c590e9abe2d0cd6Richard Röjfors free_irq(client->irq, state); 6656789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 666b13f4af25c0a36d74a69f7d30e2a28fa941e99b5Lars-Peter Clausen adv7180_exit_controls(state); 667297a0ae32bf84c8ae135971eb21f18ee5f4ca3eaLars-Peter Clausen mutex_destroy(&state->mutex); 6686789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors return 0; 6696789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors} 6706789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 6716789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic const struct i2c_device_id adv7180_id[] = { 672c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga {KBUILD_MODNAME, 0}, 6736789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors {}, 6746789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 6756789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 676cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen#ifdef CONFIG_PM_SLEEP 677cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausenstatic int adv7180_suspend(struct device *dev) 678bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga{ 679cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen struct i2c_client *client = to_i2c_client(dev); 680e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen struct v4l2_subdev *sd = i2c_get_clientdata(client); 681e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen struct adv7180_state *state = to_state(sd); 682bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 683e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen return adv7180_set_power(state, client, false); 684bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga} 685bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 686cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausenstatic int adv7180_resume(struct device *dev) 687bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga{ 688cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen struct i2c_client *client = to_i2c_client(dev); 689bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct v4l2_subdev *sd = i2c_get_clientdata(client); 690bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga struct adv7180_state *state = to_state(sd); 691bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga int ret; 692bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 693e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen if (state->powered) { 694e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen ret = adv7180_set_power(state, client, true); 695e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen if (ret) 696e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen return ret; 697e246c3332daa885e911630922ee08c7956dfea0eLars-Peter Clausen } 698bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga ret = init_device(client, state); 699bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga if (ret < 0) 700bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return ret; 701bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga return 0; 702bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga} 703cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen 704cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausenstatic SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); 705cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen#define ADV7180_PM_OPS (&adv7180_pm_ops) 706cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen 707cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen#else 708cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen#define ADV7180_PM_OPS NULL 709bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga#endif 710bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga 7116789cb5230f8b06271b6a89ace20449af14be303Richard RöjforsMODULE_DEVICE_TABLE(i2c, adv7180_id); 7126789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 7136789cb5230f8b06271b6a89ace20449af14be303Richard Röjforsstatic struct i2c_driver adv7180_driver = { 7146789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors .driver = { 715bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga .owner = THIS_MODULE, 716c9fbedddc2b9cdf1b1a4a4053f52a629c0daa9a0Federico Vaga .name = KBUILD_MODNAME, 717cc1088dc0b92723c5e2e4cb5098dfa84a39afaedLars-Peter Clausen .pm = ADV7180_PM_OPS, 718bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga }, 719bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga .probe = adv7180_probe, 7204c62e9764ab403d42f9b8871b1241fe7812f19d4Greg Kroah-Hartman .remove = adv7180_remove, 721bca7ad1a332a0754860bdd57b258f8e9ee5eb2a5Federico Vaga .id_table = adv7180_id, 7226789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors}; 7236789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 724c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5Axel Linmodule_i2c_driver(adv7180_driver); 7256789cb5230f8b06271b6a89ace20449af14be303Richard Röjfors 7266789cb5230f8b06271b6a89ace20449af14be303Richard RöjforsMODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); 7276789cb5230f8b06271b6a89ace20449af14be303Richard RöjforsMODULE_AUTHOR("Mocean Laboratories"); 7286789cb5230f8b06271b6a89ace20449af14be303Richard RöjforsMODULE_LICENSE("GPL v2"); 729