1/* 2 * Driver for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM) 3 * 4 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <linux/i2c.h> 12#include <linux/init.h> 13#include <linux/platform_device.h> 14#include <linux/slab.h> 15#include <linux/videodev2.h> 16 17#include <media/ak881x.h> 18#include <media/v4l2-chip-ident.h> 19#include <media/v4l2-common.h> 20#include <media/v4l2-device.h> 21 22#define AK881X_INTERFACE_MODE 0 23#define AK881X_VIDEO_PROCESS1 1 24#define AK881X_VIDEO_PROCESS2 2 25#define AK881X_VIDEO_PROCESS3 3 26#define AK881X_DAC_MODE 5 27#define AK881X_STATUS 0x24 28#define AK881X_DEVICE_ID 0x25 29#define AK881X_DEVICE_REVISION 0x26 30 31struct ak881x { 32 struct v4l2_subdev subdev; 33 struct ak881x_pdata *pdata; 34 unsigned int lines; 35 int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */ 36 char revision; /* DEVICE_REVISION content */ 37}; 38 39static int reg_read(struct i2c_client *client, const u8 reg) 40{ 41 return i2c_smbus_read_byte_data(client, reg); 42} 43 44static int reg_write(struct i2c_client *client, const u8 reg, 45 const u8 data) 46{ 47 return i2c_smbus_write_byte_data(client, reg, data); 48} 49 50static int reg_set(struct i2c_client *client, const u8 reg, 51 const u8 data, u8 mask) 52{ 53 int ret = reg_read(client, reg); 54 if (ret < 0) 55 return ret; 56 return reg_write(client, reg, (ret & ~mask) | (data & mask)); 57} 58 59static struct ak881x *to_ak881x(const struct i2c_client *client) 60{ 61 return container_of(i2c_get_clientdata(client), struct ak881x, subdev); 62} 63 64static int ak881x_g_chip_ident(struct v4l2_subdev *sd, 65 struct v4l2_dbg_chip_ident *id) 66{ 67 struct i2c_client *client = v4l2_get_subdevdata(sd); 68 struct ak881x *ak881x = to_ak881x(client); 69 70 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) 71 return -EINVAL; 72 73 if (id->match.addr != client->addr) 74 return -ENODEV; 75 76 id->ident = ak881x->id; 77 id->revision = ak881x->revision; 78 79 return 0; 80} 81 82#ifdef CONFIG_VIDEO_ADV_DEBUG 83static int ak881x_g_register(struct v4l2_subdev *sd, 84 struct v4l2_dbg_register *reg) 85{ 86 struct i2c_client *client = v4l2_get_subdevdata(sd); 87 88 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) 89 return -EINVAL; 90 91 if (reg->match.addr != client->addr) 92 return -ENODEV; 93 94 reg->val = reg_read(client, reg->reg); 95 96 if (reg->val > 0xffff) 97 return -EIO; 98 99 return 0; 100} 101 102static int ak881x_s_register(struct v4l2_subdev *sd, 103 struct v4l2_dbg_register *reg) 104{ 105 struct i2c_client *client = v4l2_get_subdevdata(sd); 106 107 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) 108 return -EINVAL; 109 110 if (reg->match.addr != client->addr) 111 return -ENODEV; 112 113 if (reg_write(client, reg->reg, reg->val) < 0) 114 return -EIO; 115 116 return 0; 117} 118#endif 119 120static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd, 121 struct v4l2_mbus_framefmt *mf) 122{ 123 struct i2c_client *client = v4l2_get_subdevdata(sd); 124 struct ak881x *ak881x = to_ak881x(client); 125 126 v4l_bound_align_image(&mf->width, 0, 720, 2, 127 &mf->height, 0, ak881x->lines, 1, 0); 128 mf->field = V4L2_FIELD_INTERLACED; 129 mf->code = V4L2_MBUS_FMT_YUYV8_2X8; 130 mf->colorspace = V4L2_COLORSPACE_SMPTE170M; 131 132 return 0; 133} 134 135static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd, 136 struct v4l2_mbus_framefmt *mf) 137{ 138 if (mf->field != V4L2_FIELD_INTERLACED || 139 mf->code != V4L2_MBUS_FMT_YUYV8_2X8) 140 return -EINVAL; 141 142 return ak881x_try_g_mbus_fmt(sd, mf); 143} 144 145static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, 146 enum v4l2_mbus_pixelcode *code) 147{ 148 if (index) 149 return -EINVAL; 150 151 *code = V4L2_MBUS_FMT_YUYV8_2X8; 152 return 0; 153} 154 155static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 156{ 157 struct i2c_client *client = v4l2_get_subdevdata(sd); 158 struct ak881x *ak881x = to_ak881x(client); 159 160 a->bounds.left = 0; 161 a->bounds.top = 0; 162 a->bounds.width = 720; 163 a->bounds.height = ak881x->lines; 164 a->defrect = a->bounds; 165 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 166 a->pixelaspect.numerator = 1; 167 a->pixelaspect.denominator = 1; 168 169 return 0; 170} 171 172static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 173{ 174 struct i2c_client *client = v4l2_get_subdevdata(sd); 175 struct ak881x *ak881x = to_ak881x(client); 176 u8 vp1; 177 178 if (std == V4L2_STD_NTSC_443) { 179 vp1 = 3; 180 ak881x->lines = 480; 181 } else if (std == V4L2_STD_PAL_M) { 182 vp1 = 5; 183 ak881x->lines = 480; 184 } else if (std == V4L2_STD_PAL_60) { 185 vp1 = 7; 186 ak881x->lines = 480; 187 } else if (std && !(std & ~V4L2_STD_PAL)) { 188 vp1 = 0xf; 189 ak881x->lines = 576; 190 } else if (std && !(std & ~V4L2_STD_NTSC)) { 191 vp1 = 0; 192 ak881x->lines = 480; 193 } else { 194 /* No SECAM or PAL_N/Nc supported */ 195 return -EINVAL; 196 } 197 198 reg_set(client, AK881X_VIDEO_PROCESS1, vp1, 0xf); 199 200 return 0; 201} 202 203static int ak881x_s_stream(struct v4l2_subdev *sd, int enable) 204{ 205 struct i2c_client *client = v4l2_get_subdevdata(sd); 206 struct ak881x *ak881x = to_ak881x(client); 207 208 if (enable) { 209 u8 dac; 210 /* For colour-bar testing set bit 6 of AK881X_VIDEO_PROCESS1 */ 211 /* Default: composite output */ 212 if (ak881x->pdata->flags & AK881X_COMPONENT) 213 dac = 3; 214 else 215 dac = 4; 216 /* Turn on the DAC(s) */ 217 reg_write(client, AK881X_DAC_MODE, dac); 218 dev_dbg(&client->dev, "chip status 0x%x\n", 219 reg_read(client, AK881X_STATUS)); 220 } else { 221 /* ...and clear bit 6 of AK881X_VIDEO_PROCESS1 here */ 222 reg_write(client, AK881X_DAC_MODE, 0); 223 dev_dbg(&client->dev, "chip status 0x%x\n", 224 reg_read(client, AK881X_STATUS)); 225 } 226 227 return 0; 228} 229 230static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = { 231 .g_chip_ident = ak881x_g_chip_ident, 232#ifdef CONFIG_VIDEO_ADV_DEBUG 233 .g_register = ak881x_g_register, 234 .s_register = ak881x_s_register, 235#endif 236}; 237 238static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = { 239 .s_mbus_fmt = ak881x_s_mbus_fmt, 240 .g_mbus_fmt = ak881x_try_g_mbus_fmt, 241 .try_mbus_fmt = ak881x_try_g_mbus_fmt, 242 .cropcap = ak881x_cropcap, 243 .enum_mbus_fmt = ak881x_enum_mbus_fmt, 244 .s_std_output = ak881x_s_std_output, 245 .s_stream = ak881x_s_stream, 246}; 247 248static struct v4l2_subdev_ops ak881x_subdev_ops = { 249 .core = &ak881x_subdev_core_ops, 250 .video = &ak881x_subdev_video_ops, 251}; 252 253static int ak881x_probe(struct i2c_client *client, 254 const struct i2c_device_id *did) 255{ 256 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 257 struct ak881x *ak881x; 258 u8 ifmode, data; 259 260 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 261 dev_warn(&adapter->dev, 262 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); 263 return -EIO; 264 } 265 266 ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); 267 if (!ak881x) 268 return -ENOMEM; 269 270 v4l2_i2c_subdev_init(&ak881x->subdev, client, &ak881x_subdev_ops); 271 272 data = reg_read(client, AK881X_DEVICE_ID); 273 274 switch (data) { 275 case 0x13: 276 ak881x->id = V4L2_IDENT_AK8813; 277 break; 278 case 0x14: 279 ak881x->id = V4L2_IDENT_AK8814; 280 break; 281 default: 282 dev_err(&client->dev, 283 "No ak881x chip detected, register read %x\n", data); 284 kfree(ak881x); 285 return -ENODEV; 286 } 287 288 ak881x->revision = reg_read(client, AK881X_DEVICE_REVISION); 289 ak881x->pdata = client->dev.platform_data; 290 291 if (ak881x->pdata) { 292 if (ak881x->pdata->flags & AK881X_FIELD) 293 ifmode = 4; 294 else 295 ifmode = 0; 296 297 switch (ak881x->pdata->flags & AK881X_IF_MODE_MASK) { 298 case AK881X_IF_MODE_BT656: 299 ifmode |= 1; 300 break; 301 case AK881X_IF_MODE_MASTER: 302 ifmode |= 2; 303 break; 304 case AK881X_IF_MODE_SLAVE: 305 default: 306 break; 307 } 308 309 dev_dbg(&client->dev, "IF mode %x\n", ifmode); 310 311 /* 312 * "Line Blanking No." seems to be the same as the number of 313 * "black" lines on, e.g., SuperH VOU, whose default value of 20 314 * "incidentally" matches ak881x' default 315 */ 316 reg_write(client, AK881X_INTERFACE_MODE, ifmode | (20 << 3)); 317 } 318 319 /* Hardware default: NTSC-M */ 320 ak881x->lines = 480; 321 322 dev_info(&client->dev, "Detected an ak881x chip ID %x, revision %x\n", 323 data, ak881x->revision); 324 325 return 0; 326} 327 328static int ak881x_remove(struct i2c_client *client) 329{ 330 struct ak881x *ak881x = to_ak881x(client); 331 332 v4l2_device_unregister_subdev(&ak881x->subdev); 333 kfree(ak881x); 334 335 return 0; 336} 337 338static const struct i2c_device_id ak881x_id[] = { 339 { "ak8813", 0 }, 340 { "ak8814", 0 }, 341 { } 342}; 343MODULE_DEVICE_TABLE(i2c, ak881x_id); 344 345static struct i2c_driver ak881x_i2c_driver = { 346 .driver = { 347 .name = "ak881x", 348 }, 349 .probe = ak881x_probe, 350 .remove = ak881x_remove, 351 .id_table = ak881x_id, 352}; 353 354static int __init ak881x_module_init(void) 355{ 356 return i2c_add_driver(&ak881x_i2c_driver); 357} 358 359static void __exit ak881x_module_exit(void) 360{ 361 i2c_del_driver(&ak881x_i2c_driver); 362} 363 364module_init(ak881x_module_init); 365module_exit(ak881x_module_exit); 366 367MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); 368MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); 369MODULE_LICENSE("GPL v2"); 370