Merge remote-tracking branch 'asoc/fix/wm8350' into tmp
[firefly-linux-kernel-4.4.55.git] / drivers / media / i2c / adv7343.c
index 2b5aa676a84e0066ffa6f1652be8c2d808f4c2c9..9fc2b985df0e191e4a0b7f908180b1e5d6ca6c5b 100644 (file)
@@ -43,6 +43,7 @@ MODULE_PARM_DESC(debug, "Debug level 0-1");
 struct adv7343_state {
        struct v4l2_subdev sd;
        struct v4l2_ctrl_handler hdl;
+       const struct adv7343_platform_data *pdata;
        u8 reg00;
        u8 reg01;
        u8 reg02;
@@ -215,12 +216,23 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
        /* Enable Appropriate DAC */
        val = state->reg00 & 0x03;
 
-       if (output_type == ADV7343_COMPOSITE_ID)
-               val |= ADV7343_COMPOSITE_POWER_VALUE;
-       else if (output_type == ADV7343_COMPONENT_ID)
-               val |= ADV7343_COMPONENT_POWER_VALUE;
+       /* configure default configuration */
+       if (!state->pdata)
+               if (output_type == ADV7343_COMPOSITE_ID)
+                       val |= ADV7343_COMPOSITE_POWER_VALUE;
+               else if (output_type == ADV7343_COMPONENT_ID)
+                       val |= ADV7343_COMPONENT_POWER_VALUE;
+               else
+                       val |= ADV7343_SVIDEO_POWER_VALUE;
        else
-               val |= ADV7343_SVIDEO_POWER_VALUE;
+               val = state->pdata->mode_config.sleep_mode << 0 |
+                     state->pdata->mode_config.pll_control << 1 |
+                     state->pdata->mode_config.dac_3 << 2 |
+                     state->pdata->mode_config.dac_2 << 3 |
+                     state->pdata->mode_config.dac_1 << 4 |
+                     state->pdata->mode_config.dac_6 << 5 |
+                     state->pdata->mode_config.dac_5 << 6 |
+                     state->pdata->mode_config.dac_4 << 7;
 
        err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
        if (err < 0)
@@ -238,6 +250,17 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
 
        /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
        val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
+
+       if (state->pdata && state->pdata->sd_config.sd_dac_out1)
+               val = val | (state->pdata->sd_config.sd_dac_out1 << 1);
+       else if (state->pdata && !state->pdata->sd_config.sd_dac_out1)
+               val = val & ~(state->pdata->sd_config.sd_dac_out1 << 1);
+
+       if (state->pdata && state->pdata->sd_config.sd_dac_out2)
+               val = val | (state->pdata->sd_config.sd_dac_out2 << 2);
+       else if (state->pdata && !state->pdata->sd_config.sd_dac_out2)
+               val = val & ~(state->pdata->sd_config.sd_dac_out2 << 2);
+
        err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
        if (err < 0)
                goto setoutput_exit;
@@ -397,10 +420,14 @@ static int adv7343_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL);
+       state = devm_kzalloc(&client->dev, sizeof(struct adv7343_state),
+                            GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
 
+       /* Copy board specific information here */
+       state->pdata = client->dev.platform_data;
+
        state->reg00    = 0x80;
        state->reg01    = 0x00;
        state->reg02    = 0x20;
@@ -431,16 +458,13 @@ static int adv7343_probe(struct i2c_client *client,
                int err = state->hdl.error;
 
                v4l2_ctrl_handler_free(&state->hdl);
-               kfree(state);
                return err;
        }
        v4l2_ctrl_handler_setup(&state->hdl);
 
        err = adv7343_initialize(&state->sd);
-       if (err) {
+       if (err)
                v4l2_ctrl_handler_free(&state->hdl);
-               kfree(state);
-       }
        return err;
 }
 
@@ -451,7 +475,6 @@ static int adv7343_remove(struct i2c_client *client)
 
        v4l2_device_unregister_subdev(sd);
        v4l2_ctrl_handler_free(&state->hdl);
-       kfree(state);
 
        return 0;
 }