0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <linux/types.h>
0016 #include <linux/slab.h>
0017 #include <linux/ioctl.h>
0018 #include <linux/uaccess.h>
0019 #include <linux/i2c.h>
0020 #include <linux/videodev2.h>
0021 #include <media/v4l2-device.h>
0022
0023 MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
0024 MODULE_AUTHOR("Dave Perks");
0025 MODULE_LICENSE("GPL");
0026
0027 static int debug;
0028 module_param(debug, int, 0);
0029 MODULE_PARM_DESC(debug, "Debug level (0-1)");
0030
0031
0032
0033
0034 struct saa7185 {
0035 struct v4l2_subdev sd;
0036 unsigned char reg[128];
0037
0038 v4l2_std_id norm;
0039 };
0040
0041 static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
0042 {
0043 return container_of(sd, struct saa7185, sd);
0044 }
0045
0046
0047
0048 static inline int saa7185_read(struct v4l2_subdev *sd)
0049 {
0050 struct i2c_client *client = v4l2_get_subdevdata(sd);
0051
0052 return i2c_smbus_read_byte(client);
0053 }
0054
0055 static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
0056 {
0057 struct i2c_client *client = v4l2_get_subdevdata(sd);
0058 struct saa7185 *encoder = to_saa7185(sd);
0059
0060 v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
0061 encoder->reg[reg] = value;
0062 return i2c_smbus_write_byte_data(client, reg, value);
0063 }
0064
0065 static int saa7185_write_block(struct v4l2_subdev *sd,
0066 const u8 *data, unsigned int len)
0067 {
0068 struct i2c_client *client = v4l2_get_subdevdata(sd);
0069 struct saa7185 *encoder = to_saa7185(sd);
0070 int ret = -1;
0071 u8 reg;
0072
0073
0074
0075 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0076
0077 u8 block_data[32];
0078 int block_len;
0079
0080 while (len >= 2) {
0081 block_len = 0;
0082 block_data[block_len++] = reg = data[0];
0083 do {
0084 block_data[block_len++] =
0085 encoder->reg[reg++] = data[1];
0086 len -= 2;
0087 data += 2;
0088 } while (len >= 2 && data[0] == reg && block_len < 32);
0089 ret = i2c_master_send(client, block_data, block_len);
0090 if (ret < 0)
0091 break;
0092 }
0093 } else {
0094
0095 while (len >= 2) {
0096 reg = *data++;
0097 ret = saa7185_write(sd, reg, *data++);
0098 if (ret < 0)
0099 break;
0100 len -= 2;
0101 }
0102 }
0103
0104 return ret;
0105 }
0106
0107
0108
0109 static const unsigned char init_common[] = {
0110 0x3a, 0x0f,
0111
0112
0113 0x42, 0x6b,
0114 0x43, 0x00,
0115 0x44, 0x00,
0116 0x45, 0x22,
0117 0x46, 0xac,
0118 0x47, 0x0e,
0119 0x48, 0x03,
0120 0x49, 0x1d,
0121 0x4a, 0xac,
0122 0x4b, 0xf0,
0123 0x4c, 0xc8,
0124 0x4d, 0xb9,
0125 0x4e, 0xd4,
0126 0x4f, 0x38,
0127 0x50, 0x47,
0128 0x51, 0xc1,
0129 0x52, 0xe3,
0130 0x53, 0x54,
0131 0x54, 0xa3,
0132 0x55, 0x54,
0133 0x56, 0xf2,
0134 0x57, 0x90,
0135 0x58, 0x00,
0136 0x59, 0x00,
0137
0138 0x5a, 0x00,
0139 0x5b, 0x76,
0140 0x5c, 0xa5,
0141 0x5d, 0x3c,
0142 0x5e, 0x3a,
0143 0x5f, 0x3a,
0144 0x60, 0x00,
0145
0146
0147
0148 0x67, 0x00,
0149 0x68, 0x00,
0150 0x69, 0x00,
0151 0x6a, 0x00,
0152
0153 0x6b, 0x91,
0154 0x6c, 0x20,
0155
0156 0x6d, 0x00,
0157
0158 0x6e, 0x0e,
0159
0160 0x6f, 0x00,
0161 0x70, 0x20,
0162
0163
0164
0165 0x71, 0x15,
0166 0x72, 0x90,
0167 0x73, 0x61,
0168 0x74, 0x00,
0169 0x75, 0x00,
0170 0x76, 0x00,
0171 0x77, 0x15,
0172 0x78, 0x90,
0173 0x79, 0x61,
0174
0175
0176
0177 0x7a, 0x70,
0178
0179
0180
0181 0x7b, 0x16,
0182 0x7c, 0x35,
0183 0x7d, 0x20,
0184 };
0185
0186 static const unsigned char init_pal[] = {
0187 0x61, 0x1e,
0188
0189 0x62, 0xc8,
0190 0x63, 0xcb,
0191 0x64, 0x8a,
0192 0x65, 0x09,
0193 0x66, 0x2a,
0194 };
0195
0196 static const unsigned char init_ntsc[] = {
0197 0x61, 0x1d,
0198
0199 0x62, 0xe6,
0200 0x63, 0x1f,
0201 0x64, 0x7c,
0202 0x65, 0xf0,
0203 0x66, 0x21,
0204 };
0205
0206
0207 static int saa7185_init(struct v4l2_subdev *sd, u32 val)
0208 {
0209 struct saa7185 *encoder = to_saa7185(sd);
0210
0211 saa7185_write_block(sd, init_common, sizeof(init_common));
0212 if (encoder->norm & V4L2_STD_NTSC)
0213 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
0214 else
0215 saa7185_write_block(sd, init_pal, sizeof(init_pal));
0216 return 0;
0217 }
0218
0219 static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
0220 {
0221 struct saa7185 *encoder = to_saa7185(sd);
0222
0223 if (std & V4L2_STD_NTSC)
0224 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
0225 else if (std & V4L2_STD_PAL)
0226 saa7185_write_block(sd, init_pal, sizeof(init_pal));
0227 else
0228 return -EINVAL;
0229 encoder->norm = std;
0230 return 0;
0231 }
0232
0233 static int saa7185_s_routing(struct v4l2_subdev *sd,
0234 u32 input, u32 output, u32 config)
0235 {
0236 struct saa7185 *encoder = to_saa7185(sd);
0237
0238
0239
0240
0241 switch (input) {
0242 case 0:
0243
0244 saa7185_write(sd, 0x3a, 0x0f);
0245
0246 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
0247 saa7185_write(sd, 0x6e, 0x01);
0248 break;
0249
0250 case 1:
0251
0252 saa7185_write(sd, 0x3a, 0x0f);
0253
0254 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
0255
0256 saa7185_write(sd, 0x6e, 0x00);
0257 break;
0258
0259 case 2:
0260
0261 saa7185_write(sd, 0x3a, 0x8f);
0262
0263 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
0264
0265 saa7185_write(sd, 0x6e, 0x01);
0266 break;
0267
0268 default:
0269 return -EINVAL;
0270 }
0271 return 0;
0272 }
0273
0274
0275
0276 static const struct v4l2_subdev_core_ops saa7185_core_ops = {
0277 .init = saa7185_init,
0278 };
0279
0280 static const struct v4l2_subdev_video_ops saa7185_video_ops = {
0281 .s_std_output = saa7185_s_std_output,
0282 .s_routing = saa7185_s_routing,
0283 };
0284
0285 static const struct v4l2_subdev_ops saa7185_ops = {
0286 .core = &saa7185_core_ops,
0287 .video = &saa7185_video_ops,
0288 };
0289
0290
0291
0292
0293 static int saa7185_probe(struct i2c_client *client,
0294 const struct i2c_device_id *id)
0295 {
0296 int i;
0297 struct saa7185 *encoder;
0298 struct v4l2_subdev *sd;
0299
0300
0301 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0302 return -ENODEV;
0303
0304 v4l_info(client, "chip found @ 0x%x (%s)\n",
0305 client->addr << 1, client->adapter->name);
0306
0307 encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
0308 if (encoder == NULL)
0309 return -ENOMEM;
0310 encoder->norm = V4L2_STD_NTSC;
0311 sd = &encoder->sd;
0312 v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
0313
0314 i = saa7185_write_block(sd, init_common, sizeof(init_common));
0315 if (i >= 0)
0316 i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
0317 if (i < 0)
0318 v4l2_dbg(1, debug, sd, "init error %d\n", i);
0319 else
0320 v4l2_dbg(1, debug, sd, "revision 0x%x\n",
0321 saa7185_read(sd) >> 5);
0322 return 0;
0323 }
0324
0325 static int saa7185_remove(struct i2c_client *client)
0326 {
0327 struct v4l2_subdev *sd = i2c_get_clientdata(client);
0328 struct saa7185 *encoder = to_saa7185(sd);
0329
0330 v4l2_device_unregister_subdev(sd);
0331
0332 saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
0333 return 0;
0334 }
0335
0336
0337
0338 static const struct i2c_device_id saa7185_id[] = {
0339 { "saa7185", 0 },
0340 { }
0341 };
0342 MODULE_DEVICE_TABLE(i2c, saa7185_id);
0343
0344 static struct i2c_driver saa7185_driver = {
0345 .driver = {
0346 .name = "saa7185",
0347 },
0348 .probe = saa7185_probe,
0349 .remove = saa7185_remove,
0350 .id_table = saa7185_id,
0351 };
0352
0353 module_i2c_driver(saa7185_driver);