1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun gpio functions.
4*4882a593Smuzhiyun Merging GPIO support into driver:
5*4882a593Smuzhiyun Copyright (C) 2004 Chris Kennedy <c@groovy.org>
6*4882a593Smuzhiyun Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "ivtv-driver.h"
11*4882a593Smuzhiyun #include "ivtv-cards.h"
12*4882a593Smuzhiyun #include "ivtv-gpio.h"
13*4882a593Smuzhiyun #include "tuner-xc2028.h"
14*4882a593Smuzhiyun #include <media/tuner.h>
15*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun * GPIO assignment of Yuan MPG600/MPG160
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0
21*4882a593Smuzhiyun * OUTPUT IN1 IN0 AM3 AM2 AM1 AM0
22*4882a593Smuzhiyun * INPUT DM1 DM0
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * IN* : Input selection
25*4882a593Smuzhiyun * IN1 IN0
26*4882a593Smuzhiyun * 1 1 N/A
27*4882a593Smuzhiyun * 1 0 Line
28*4882a593Smuzhiyun * 0 1 N/A
29*4882a593Smuzhiyun * 0 0 Tuner
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * AM* : Audio Mode
32*4882a593Smuzhiyun * AM3 0: Normal 1: Mixed(Sub+Main channel)
33*4882a593Smuzhiyun * AM2 0: Subchannel 1: Main channel
34*4882a593Smuzhiyun * AM1 0: Stereo 1: Mono
35*4882a593Smuzhiyun * AM0 0: Normal 1: Mute
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * DM* : Detected tuner audio Mode
38*4882a593Smuzhiyun * DM1 0: Stereo 1: Mono
39*4882a593Smuzhiyun * DM0 0: Multiplex 1: Normal
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun * GPIO Initial Settings
42*4882a593Smuzhiyun * MPG600 MPG160
43*4882a593Smuzhiyun * DIR 0x3080 0x7080
44*4882a593Smuzhiyun * OUTPUT 0x000C 0x400C
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun * Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous
47*4882a593Smuzhiyun * for analyzing GPIO of MPG160.
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun *****************************************************************************
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * GPIO assignment of Avermedia M179 (per information direct from AVerMedia)
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0
54*4882a593Smuzhiyun * OUTPUT IN0 AM0 IN1 AM1 AM2 IN2 BR0 BR1
55*4882a593Smuzhiyun * INPUT
56*4882a593Smuzhiyun *
57*4882a593Smuzhiyun * IN* : Input selection
58*4882a593Smuzhiyun * IN0 IN1 IN2
59*4882a593Smuzhiyun * * 1 * Mute
60*4882a593Smuzhiyun * 0 0 0 Line-In
61*4882a593Smuzhiyun * 1 0 0 TV Tuner Audio
62*4882a593Smuzhiyun * 0 0 1 FM Audio
63*4882a593Smuzhiyun * 1 0 1 Mute
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * AM* : Audio Mode
66*4882a593Smuzhiyun * AM0 AM1 AM2
67*4882a593Smuzhiyun * 0 0 0 TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP
68*4882a593Smuzhiyun * 0 0 1 TV Tuner Audio: L_OUT=R_OUT=SAP (SAP)
69*4882a593Smuzhiyun * 0 1 0 TV Tuner Audio: L_OUT=L, R_OUT=R (stereo)
70*4882a593Smuzhiyun * 0 1 1 TV Tuner Audio: mute
71*4882a593Smuzhiyun * 1 * * TV Tuner Audio: L_OUT=R_OUT=(L+R)/2 (mono)
72*4882a593Smuzhiyun *
73*4882a593Smuzhiyun * BR* : Audio Sample Rate (BR stands for bitrate for some reason)
74*4882a593Smuzhiyun * BR0 BR1
75*4882a593Smuzhiyun * 0 0 32 kHz
76*4882a593Smuzhiyun * 0 1 44.1 kHz
77*4882a593Smuzhiyun * 1 0 48 kHz
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * DM* : Detected tuner audio Mode
80*4882a593Smuzhiyun * Unknown currently
81*4882a593Smuzhiyun *
82*4882a593Smuzhiyun * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at
83*4882a593Smuzhiyun * AVerMedia for providing the GPIO information used to add support
84*4882a593Smuzhiyun * for the M179 cards.
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /********************* GPIO stuffs *********************/
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* GPIO registers */
90*4882a593Smuzhiyun #define IVTV_REG_GPIO_IN 0x9008
91*4882a593Smuzhiyun #define IVTV_REG_GPIO_OUT 0x900c
92*4882a593Smuzhiyun #define IVTV_REG_GPIO_DIR 0x9020
93*4882a593Smuzhiyun
ivtv_reset_ir_gpio(struct ivtv * itv)94*4882a593Smuzhiyun void ivtv_reset_ir_gpio(struct ivtv *itv)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun int curdir, curout;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun if (itv->card->type != IVTV_CARD_PVR_150)
99*4882a593Smuzhiyun return;
100*4882a593Smuzhiyun IVTV_DEBUG_INFO("Resetting PVR150 IR\n");
101*4882a593Smuzhiyun curout = read_reg(IVTV_REG_GPIO_OUT);
102*4882a593Smuzhiyun curdir = read_reg(IVTV_REG_GPIO_DIR);
103*4882a593Smuzhiyun curdir |= 0x80;
104*4882a593Smuzhiyun write_reg(curdir, IVTV_REG_GPIO_DIR);
105*4882a593Smuzhiyun curout = (curout & ~0xF) | 1;
106*4882a593Smuzhiyun write_reg(curout, IVTV_REG_GPIO_OUT);
107*4882a593Smuzhiyun /* We could use something else for smaller time */
108*4882a593Smuzhiyun schedule_timeout_interruptible(msecs_to_jiffies(1));
109*4882a593Smuzhiyun curout |= 2;
110*4882a593Smuzhiyun write_reg(curout, IVTV_REG_GPIO_OUT);
111*4882a593Smuzhiyun curdir &= ~0x80;
112*4882a593Smuzhiyun write_reg(curdir, IVTV_REG_GPIO_DIR);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Xceive tuner reset function */
ivtv_reset_tuner_gpio(void * dev,int component,int cmd,int value)116*4882a593Smuzhiyun int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun struct i2c_algo_bit_data *algo = dev;
119*4882a593Smuzhiyun struct ivtv *itv = algo->data;
120*4882a593Smuzhiyun u32 curout;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun if (cmd != XC2028_TUNER_RESET)
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun IVTV_DEBUG_INFO("Resetting tuner\n");
125*4882a593Smuzhiyun curout = read_reg(IVTV_REG_GPIO_OUT);
126*4882a593Smuzhiyun curout &= ~(1 << itv->card->xceive_pin);
127*4882a593Smuzhiyun write_reg(curout, IVTV_REG_GPIO_OUT);
128*4882a593Smuzhiyun schedule_timeout_interruptible(msecs_to_jiffies(1));
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun curout |= 1 << itv->card->xceive_pin;
131*4882a593Smuzhiyun write_reg(curout, IVTV_REG_GPIO_OUT);
132*4882a593Smuzhiyun schedule_timeout_interruptible(msecs_to_jiffies(1));
133*4882a593Smuzhiyun return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
sd_to_ivtv(struct v4l2_subdev * sd)136*4882a593Smuzhiyun static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun return container_of(sd, struct ivtv, sd_gpio);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
to_sd(struct v4l2_ctrl * ctrl)141*4882a593Smuzhiyun static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
subdev_s_clock_freq(struct v4l2_subdev * sd,u32 freq)146*4882a593Smuzhiyun static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
149*4882a593Smuzhiyun u16 mask, data;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun mask = itv->card->gpio_audio_freq.mask;
152*4882a593Smuzhiyun switch (freq) {
153*4882a593Smuzhiyun case 32000:
154*4882a593Smuzhiyun data = itv->card->gpio_audio_freq.f32000;
155*4882a593Smuzhiyun break;
156*4882a593Smuzhiyun case 44100:
157*4882a593Smuzhiyun data = itv->card->gpio_audio_freq.f44100;
158*4882a593Smuzhiyun break;
159*4882a593Smuzhiyun case 48000:
160*4882a593Smuzhiyun default:
161*4882a593Smuzhiyun data = itv->card->gpio_audio_freq.f48000;
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun if (mask)
165*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
166*4882a593Smuzhiyun return 0;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
subdev_g_tuner(struct v4l2_subdev * sd,struct v4l2_tuner * vt)169*4882a593Smuzhiyun static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
172*4882a593Smuzhiyun u16 mask;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun mask = itv->card->gpio_audio_detect.mask;
175*4882a593Smuzhiyun if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
176*4882a593Smuzhiyun vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
177*4882a593Smuzhiyun V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
178*4882a593Smuzhiyun else
179*4882a593Smuzhiyun vt->rxsubchans = V4L2_TUNER_SUB_MONO;
180*4882a593Smuzhiyun return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
subdev_s_tuner(struct v4l2_subdev * sd,const struct v4l2_tuner * vt)183*4882a593Smuzhiyun static int subdev_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
186*4882a593Smuzhiyun u16 mask, data;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun mask = itv->card->gpio_audio_mode.mask;
189*4882a593Smuzhiyun switch (vt->audmode) {
190*4882a593Smuzhiyun case V4L2_TUNER_MODE_LANG1:
191*4882a593Smuzhiyun data = itv->card->gpio_audio_mode.lang1;
192*4882a593Smuzhiyun break;
193*4882a593Smuzhiyun case V4L2_TUNER_MODE_LANG2:
194*4882a593Smuzhiyun data = itv->card->gpio_audio_mode.lang2;
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun case V4L2_TUNER_MODE_MONO:
197*4882a593Smuzhiyun data = itv->card->gpio_audio_mode.mono;
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun case V4L2_TUNER_MODE_STEREO:
200*4882a593Smuzhiyun case V4L2_TUNER_MODE_LANG1_LANG2:
201*4882a593Smuzhiyun default:
202*4882a593Smuzhiyun data = itv->card->gpio_audio_mode.stereo;
203*4882a593Smuzhiyun break;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun if (mask)
206*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
207*4882a593Smuzhiyun return 0;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
subdev_s_radio(struct v4l2_subdev * sd)210*4882a593Smuzhiyun static int subdev_s_radio(struct v4l2_subdev *sd)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
213*4882a593Smuzhiyun u16 mask, data;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun mask = itv->card->gpio_audio_input.mask;
216*4882a593Smuzhiyun data = itv->card->gpio_audio_input.radio;
217*4882a593Smuzhiyun if (mask)
218*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
219*4882a593Smuzhiyun return 0;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
subdev_s_audio_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)222*4882a593Smuzhiyun static int subdev_s_audio_routing(struct v4l2_subdev *sd,
223*4882a593Smuzhiyun u32 input, u32 output, u32 config)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
226*4882a593Smuzhiyun u16 mask, data;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (input > 2)
229*4882a593Smuzhiyun return -EINVAL;
230*4882a593Smuzhiyun mask = itv->card->gpio_audio_input.mask;
231*4882a593Smuzhiyun switch (input) {
232*4882a593Smuzhiyun case 0:
233*4882a593Smuzhiyun data = itv->card->gpio_audio_input.tuner;
234*4882a593Smuzhiyun break;
235*4882a593Smuzhiyun case 1:
236*4882a593Smuzhiyun data = itv->card->gpio_audio_input.linein;
237*4882a593Smuzhiyun break;
238*4882a593Smuzhiyun case 2:
239*4882a593Smuzhiyun default:
240*4882a593Smuzhiyun data = itv->card->gpio_audio_input.radio;
241*4882a593Smuzhiyun break;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun if (mask)
244*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
245*4882a593Smuzhiyun return 0;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
subdev_s_ctrl(struct v4l2_ctrl * ctrl)248*4882a593Smuzhiyun static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun struct v4l2_subdev *sd = to_sd(ctrl);
251*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
252*4882a593Smuzhiyun u16 mask, data;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun switch (ctrl->id) {
255*4882a593Smuzhiyun case V4L2_CID_AUDIO_MUTE:
256*4882a593Smuzhiyun mask = itv->card->gpio_audio_mute.mask;
257*4882a593Smuzhiyun data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
258*4882a593Smuzhiyun if (mask)
259*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
260*4882a593Smuzhiyun (data & mask), IVTV_REG_GPIO_OUT);
261*4882a593Smuzhiyun return 0;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun return -EINVAL;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun
subdev_log_status(struct v4l2_subdev * sd)267*4882a593Smuzhiyun static int subdev_log_status(struct v4l2_subdev *sd)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
272*4882a593Smuzhiyun read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
273*4882a593Smuzhiyun read_reg(IVTV_REG_GPIO_IN));
274*4882a593Smuzhiyun v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
subdev_s_video_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)278*4882a593Smuzhiyun static int subdev_s_video_routing(struct v4l2_subdev *sd,
279*4882a593Smuzhiyun u32 input, u32 output, u32 config)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun struct ivtv *itv = sd_to_ivtv(sd);
282*4882a593Smuzhiyun u16 mask, data;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */
285*4882a593Smuzhiyun return -EINVAL;
286*4882a593Smuzhiyun mask = itv->card->gpio_video_input.mask;
287*4882a593Smuzhiyun if (input == 0)
288*4882a593Smuzhiyun data = itv->card->gpio_video_input.tuner;
289*4882a593Smuzhiyun else if (input == 1)
290*4882a593Smuzhiyun data = itv->card->gpio_video_input.composite;
291*4882a593Smuzhiyun else
292*4882a593Smuzhiyun data = itv->card->gpio_video_input.svideo;
293*4882a593Smuzhiyun if (mask)
294*4882a593Smuzhiyun write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
295*4882a593Smuzhiyun return 0;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
299*4882a593Smuzhiyun .s_ctrl = subdev_s_ctrl,
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops subdev_core_ops = {
303*4882a593Smuzhiyun .log_status = subdev_log_status,
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
307*4882a593Smuzhiyun .s_radio = subdev_s_radio,
308*4882a593Smuzhiyun .g_tuner = subdev_g_tuner,
309*4882a593Smuzhiyun .s_tuner = subdev_s_tuner,
310*4882a593Smuzhiyun };
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
313*4882a593Smuzhiyun .s_clock_freq = subdev_s_clock_freq,
314*4882a593Smuzhiyun .s_routing = subdev_s_audio_routing,
315*4882a593Smuzhiyun };
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static const struct v4l2_subdev_video_ops subdev_video_ops = {
318*4882a593Smuzhiyun .s_routing = subdev_s_video_routing,
319*4882a593Smuzhiyun };
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun static const struct v4l2_subdev_ops subdev_ops = {
322*4882a593Smuzhiyun .core = &subdev_core_ops,
323*4882a593Smuzhiyun .tuner = &subdev_tuner_ops,
324*4882a593Smuzhiyun .audio = &subdev_audio_ops,
325*4882a593Smuzhiyun .video = &subdev_video_ops,
326*4882a593Smuzhiyun };
327*4882a593Smuzhiyun
ivtv_gpio_init(struct ivtv * itv)328*4882a593Smuzhiyun int ivtv_gpio_init(struct ivtv *itv)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun u16 pin = 0;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (itv->card->xceive_pin)
333*4882a593Smuzhiyun pin = 1 << itv->card->xceive_pin;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if ((itv->card->gpio_init.direction | pin) == 0)
336*4882a593Smuzhiyun return 0;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
339*4882a593Smuzhiyun read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /* init output data then direction */
342*4882a593Smuzhiyun write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
343*4882a593Smuzhiyun write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
344*4882a593Smuzhiyun v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
345*4882a593Smuzhiyun snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
346*4882a593Smuzhiyun itv->sd_gpio.grp_id = IVTV_HW_GPIO;
347*4882a593Smuzhiyun v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
348*4882a593Smuzhiyun v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
349*4882a593Smuzhiyun V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
350*4882a593Smuzhiyun if (itv->hdl_gpio.error)
351*4882a593Smuzhiyun return itv->hdl_gpio.error;
352*4882a593Smuzhiyun itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
353*4882a593Smuzhiyun v4l2_ctrl_handler_setup(&itv->hdl_gpio);
354*4882a593Smuzhiyun return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
355*4882a593Smuzhiyun }
356