Blame view

drivers/media/video/bt866.c 6.08 KB
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /*
      bt866 - BT866 Digital Video Encoder (Rockwell Part)
  
      Copyright (C) 1999 Mike Bernson <mike@mlb.org>
      Copyright (C) 1998 Dave Perks <dperks@ibm.net>
  
      Modifications for LML33/DC10plus unified driver
      Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
  
      This code was modify/ported from the saa7111 driver written
      by Dave Perks.
  
      This code was adapted for the bt866 by Christer Weinigel and ported
      to 2.6 by Martin Samuelsson.
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  
  #include <linux/module.h>
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
32
  #include <linux/types.h>
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
33
34
  #include <linux/ioctl.h>
  #include <asm/uaccess.h>
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
35
  #include <linux/i2c.h>
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
36
  #include <linux/i2c-id.h>
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
37
38
39
  #include <linux/videodev2.h>
  #include <media/v4l2-device.h>
  #include <media/v4l2-chip-ident.h>
2d26698e8   Hans Verkuil   V4L/DVB (10731): ...
40
  #include <media/v4l2-i2c-drv.h>
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
41

c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
42
43
  MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
  MODULE_AUTHOR("Mike Bernson & Dave Perks");
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
44
  MODULE_LICENSE("GPL");
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
45
46
47
  static int debug;
  module_param(debug, int, 0);
  MODULE_PARM_DESC(debug, "Debug level (0-1)");
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
48

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
49

fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
50
51
52
  /* ----------------------------------------------------------------------- */
  
  struct bt866 {
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
53
  	struct v4l2_subdev sd;
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
54
  	u8 reg[256];
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
55
  };
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
56
  static inline struct bt866 *to_bt866(struct v4l2_subdev *sd)
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
57
  {
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
58
59
60
61
62
63
  	return container_of(sd, struct bt866, sd);
  }
  
  static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data)
  {
  	struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  	u8 buffer[2];
  	int err;
  
  	buffer[0] = subaddr;
  	buffer[1] = data;
  
  	encoder->reg[subaddr] = data;
  
  	v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x
  ", subaddr, data);
  
  	for (err = 0; err < 3;) {
  		if (i2c_master_send(client, buffer, 2) == 2)
  			break;
  		err++;
  		v4l_warn(client, "error #%d writing to 0x%02x
  ",
  				err, subaddr);
  		schedule_timeout_interruptible(msecs_to_jiffies(100));
  	}
  	if (err == 3) {
  		v4l_warn(client, "giving up
  ");
  		return -1;
  	}
  
  	return 0;
  }
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
92

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
93
  static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
94
  {
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
95
96
  	v4l2_dbg(1, debug, sd, "set norm %llx
  ", std);
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
97

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
98
99
100
101
102
  	/* Only PAL supported by this driver at the moment! */
  	if (!(std & V4L2_STD_NTSC))
  		return -EINVAL;
  	return 0;
  }
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
103

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
  {
  	static const __u8 init[] = {
  		0xc8, 0xcc, /* CRSCALE */
  		0xca, 0x91, /* CBSCALE */
  		0xcc, 0x24, /* YC16 | OSDNUM */
  		0xda, 0x00, /*  */
  		0xdc, 0x24, /* SETMODE | PAL */
  		0xde, 0x02, /* EACTIVE */
  
  		/* overlay colors */
  		0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
  		0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
  		0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
  		0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
  		0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
  		0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
  		0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
  		0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
  
  		0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
  		0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
  		0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
  		0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
  		0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
  		0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
  		0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
  		0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
  	};
  	struct bt866 *encoder = to_bt866(sd);
  	u8 val;
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
  		bt866_write(encoder, init[i], init[i+1]);
  
  	val = encoder->reg[0xdc];
  
  	if (route->input == 0)
  		val |= 0x40; /* CBSWAP */
  	else
  		val &= ~0x40; /* !CBSWAP */
  
  	bt866_write(encoder, 0xdc, val);
  
  	val = encoder->reg[0xcc];
  	if (route->input == 2)
  		val |= 0x01; /* OSDBAR */
  	else
  		val &= ~0x01; /* !OSDBAR */
  	bt866_write(encoder, 0xcc, val);
  
  	v4l2_dbg(1, debug, sd, "set input %d
  ", route->input);
  
  	switch (route->input) {
  	case 0:
  	case 1:
  	case 2:
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
163
  		break;
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
164
165
  	default:
  		return -EINVAL;
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
166
  	}
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
167
168
  	return 0;
  }
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
169

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  #if 0
  /* Code to setup square pixels, might be of some use in the future,
     but is currently unused. */
  	val = encoder->reg[0xdc];
  	if (*iarg)
  		val |= 1; /* SQUARE */
  	else
  		val &= ~1; /* !SQUARE */
  	bt866_write(client, 0xdc, val);
  #endif
  
  static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
  {
  	struct i2c_client *client = v4l2_get_subdevdata(sd);
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
184

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
185
186
  	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0);
  }
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
187

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
188
  /* ----------------------------------------------------------------------- */
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
189

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
190
191
192
  static const struct v4l2_subdev_core_ops bt866_core_ops = {
  	.g_chip_ident = bt866_g_chip_ident,
  };
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
193

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
194
195
196
197
  static const struct v4l2_subdev_video_ops bt866_video_ops = {
  	.s_std_output = bt866_s_std_output,
  	.s_routing = bt866_s_routing,
  };
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
198

8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
199
200
201
202
  static const struct v4l2_subdev_ops bt866_ops = {
  	.core = &bt866_core_ops,
  	.video = &bt866_video_ops,
  };
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
203

c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
204
205
  static int bt866_probe(struct i2c_client *client,
  			const struct i2c_device_id *id)
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
206
207
  {
  	struct bt866 *encoder;
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
208
  	struct v4l2_subdev *sd;
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
209

c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
210
211
212
  	v4l_info(client, "chip found @ 0x%x (%s)
  ",
  			client->addr << 1, client->adapter->name);
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
213
214
  
  	encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
215
  	if (encoder == NULL)
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
216
  		return -ENOMEM;
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
217
218
  	sd = &encoder->sd;
  	v4l2_i2c_subdev_init(sd, client, &bt866_ops);
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
219
220
  	return 0;
  }
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
221
  static int bt866_remove(struct i2c_client *client)
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
222
  {
8e4e1d805   Hans Verkuil   V4L/DVB (10718): ...
223
224
225
226
  	struct v4l2_subdev *sd = i2c_get_clientdata(client);
  
  	v4l2_device_unregister_subdev(sd);
  	kfree(to_bt866(sd));
fbe60daac   Martin Samuelsson   V4L/DVB (3916): A...
227
228
  	return 0;
  }
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
229
230
231
232
233
234
235
236
  static const struct i2c_device_id bt866_id[] = {
  	{ "bt866", 0 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, bt866_id);
  
  static struct v4l2_i2c_driver_data v4l2_i2c_data = {
  	.name = "bt866",
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
237
238
  	.probe = bt866_probe,
  	.remove = bt866_remove,
c18fdcf65   Hans Verkuil   V4L/DVB (9202): b...
239
240
  	.id_table = bt866_id,
  };