+static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
+ struct v4l2_subdev_io_pin_config *p)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int i;
+ u32 pin_ctrl;
+ u8 gpio_oe, gpio_data, strength;
+
+ pin_ctrl = cx25840_read4(client, 0x120);
+ gpio_oe = cx25840_read(client, 0x160);
+ gpio_data = cx25840_read(client, 0x164);
+
+ for (i = 0; i < n; i++) {
+ strength = p[i].strength;
+ if (strength > CX25840_PIN_DRIVE_FAST)
+ strength = CX25840_PIN_DRIVE_FAST;
+
+ switch (p[i].pin) {
+ case CX23885_PIN_IRQ_N_GPIO16:
+ if (p[i].function != CX23885_PAD_IRQ_N) {
+ /* GPIO16 */
+ pin_ctrl &= ~(0x1 << 25);
+ } else {
+ /* IRQ_N */
+ if (p[i].flags &
+ (V4L2_SUBDEV_IO_PIN_DISABLE |
+ V4L2_SUBDEV_IO_PIN_INPUT)) {
+ pin_ctrl &= ~(0x1 << 25);
+ } else {
+ pin_ctrl |= (0x1 << 25);
+ }
+ if (p[i].flags &
+ V4L2_SUBDEV_IO_PIN_ACTIVE_LOW) {
+ pin_ctrl &= ~(0x1 << 24);
+ } else {
+ pin_ctrl |= (0x1 << 24);
+ }
+ }
+ break;
+ case CX23885_PIN_IR_RX_GPIO19:
+ if (p[i].function != CX23885_PAD_GPIO19) {
+ /* IR_RX */
+ gpio_oe |= (0x1 << 0);
+ pin_ctrl &= ~(0x3 << 18);
+ pin_ctrl |= (strength << 18);
+ } else {
+ /* GPIO19 */
+ gpio_oe &= ~(0x1 << 0);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+ gpio_data &= ~(0x1 << 0);
+ gpio_data |= ((p[i].value & 0x1) << 0);
+ }
+ pin_ctrl &= ~(0x3 << 12);
+ pin_ctrl |= (strength << 12);
+ }
+ break;
+ case CX23885_PIN_IR_TX_GPIO20:
+ if (p[i].function != CX23885_PAD_GPIO20) {
+ /* IR_TX */
+ gpio_oe |= (0x1 << 1);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_DISABLE)
+ pin_ctrl &= ~(0x1 << 10);
+ else
+ pin_ctrl |= (0x1 << 10);
+ pin_ctrl &= ~(0x3 << 18);
+ pin_ctrl |= (strength << 18);
+ } else {
+ /* GPIO20 */
+ gpio_oe &= ~(0x1 << 1);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+ gpio_data &= ~(0x1 << 1);
+ gpio_data |= ((p[i].value & 0x1) << 1);
+ }
+ pin_ctrl &= ~(0x3 << 12);
+ pin_ctrl |= (strength << 12);
+ }
+ break;
+ case CX23885_PIN_I2S_SDAT_GPIO21:
+ if (p[i].function != CX23885_PAD_GPIO21) {
+ /* I2S_SDAT */
+ /* TODO: Input or Output config */
+ gpio_oe |= (0x1 << 2);
+ pin_ctrl &= ~(0x3 << 22);
+ pin_ctrl |= (strength << 22);
+ } else {
+ /* GPIO21 */
+ gpio_oe &= ~(0x1 << 2);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+ gpio_data &= ~(0x1 << 2);
+ gpio_data |= ((p[i].value & 0x1) << 2);
+ }
+ pin_ctrl &= ~(0x3 << 12);
+ pin_ctrl |= (strength << 12);
+ }
+ break;
+ case CX23885_PIN_I2S_WCLK_GPIO22:
+ if (p[i].function != CX23885_PAD_GPIO22) {
+ /* I2S_WCLK */
+ /* TODO: Input or Output config */
+ gpio_oe |= (0x1 << 3);
+ pin_ctrl &= ~(0x3 << 22);
+ pin_ctrl |= (strength << 22);
+ } else {
+ /* GPIO22 */
+ gpio_oe &= ~(0x1 << 3);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+ gpio_data &= ~(0x1 << 3);
+ gpio_data |= ((p[i].value & 0x1) << 3);
+ }
+ pin_ctrl &= ~(0x3 << 12);
+ pin_ctrl |= (strength << 12);
+ }
+ break;
+ case CX23885_PIN_I2S_BCLK_GPIO23:
+ if (p[i].function != CX23885_PAD_GPIO23) {
+ /* I2S_BCLK */
+ /* TODO: Input or Output config */
+ gpio_oe |= (0x1 << 4);
+ pin_ctrl &= ~(0x3 << 22);
+ pin_ctrl |= (strength << 22);
+ } else {
+ /* GPIO23 */
+ gpio_oe &= ~(0x1 << 4);
+ if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+ gpio_data &= ~(0x1 << 4);
+ gpio_data |= ((p[i].value & 0x1) << 4);
+ }
+ pin_ctrl &= ~(0x3 << 12);
+ pin_ctrl |= (strength << 12);
+ }
+ break;
+ }
+ }
+
+ cx25840_write(client, 0x164, gpio_data);
+ cx25840_write(client, 0x160, gpio_oe);
+ cx25840_write4(client, 0x120, pin_ctrl);
+ return 0;
+}
+
+static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
+ struct v4l2_subdev_io_pin_config *pincfg)
+{
+ struct cx25840_state *state = to_state(sd);
+
+ if (is_cx2388x(state))
+ return cx23885_s_io_pin_config(sd, n, pincfg);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+