@@ -49,7 +49,8 @@
#define IMX335_INCLK_RATE 24000000
/* CSI2 HW configuration */
-#define IMX335_LINK_FREQ 594000000
+#define IMX335_LINK_FREQ_594MHz 594000000
+#define IMX335_LINK_FREQ_445MHz 445500000
#define IMX335_NUM_DATA_LANES 4
#define IMX335_REG_MIN 0x00
@@ -99,7 +100,6 @@ static const char * const imx335_supply_name[] = {
* @vblank_min: Minimum vertical blanking in lines
* @vblank_max: Maximum vertical blanking in lines
* @pclk: Sensor pixel clock
- * @link_freq_idx: Link frequency index
* @reg_list: Register list for sensor mode
*/
struct imx335_mode {
@@ -111,7 +111,6 @@ struct imx335_mode {
u32 vblank_min;
u32 vblank_max;
u64 pclk;
- u32 link_freq_idx;
struct imx335_reg_list reg_list;
};
@@ -133,6 +132,7 @@ struct imx335_mode {
* @again_ctrl: Pointer to analog gain control
* @vblank: Vertical blanking in lines
* @cur_mode: Pointer to current selected sensor mode
+ * @link_freq_idx: Selected link frequency index
* @mutex: Mutex for serializing sensor controls
* @cur_mbus_code: Currently selected media bus format code
*/
@@ -156,20 +156,16 @@ struct imx335 {
};
u32 vblank;
const struct imx335_mode *cur_mode;
+ u32 link_freq_idx;
struct mutex mutex;
u32 cur_mbus_code;
};
-static const s64 link_freq[] = {
- IMX335_LINK_FREQ,
-};
/* Sensor mode registers */
static const struct imx335_reg mode_2592x1940_regs[] = {
{0x3000, 0x01},
{0x3002, 0x00},
- {0x300c, 0x3b},
- {0x300d, 0x2a},
{0x3018, 0x04},
{0x302c, 0x3c},
{0x302e, 0x20},
@@ -177,10 +173,6 @@ static const struct imx335_reg mode_2592x1940_regs[] = {
{0x3074, 0xc8},
{0x3076, 0x28},
{0x304c, 0x00},
- {0x314c, 0xc6},
- {0x315a, 0x02},
- {0x3168, 0xa0},
- {0x316a, 0x7e},
{0x31a1, 0x00},
{0x3288, 0x21},
{0x328a, 0x02},
@@ -266,6 +258,65 @@ static const struct imx335_reg raw12_framefmt_regs[] = {
{0x341d, 0x00},
};
+static const struct imx335_reg mipi_data_rate_1188Mbps[] = {
+ {0x300c, 0x3b},
+ {0x300d, 0x2a},
+ {0x314c, 0xc6},
+ {0x314d, 0x00},
+ {0x315a, 0x02},
+ {0x3168, 0xa0},
+ {0x316a, 0x7e},
+ {0x319e, 0x01},
+ {0x3a18, 0x8f},
+ {0x3a1a, 0x4f},
+ {0x3a1c, 0x47},
+ {0x3a1e, 0x37},
+ {0x3a1f, 0x01},
+ {0x3a20, 0x4f},
+ {0x3a22, 0x87},
+ {0x3a24, 0x4f},
+ {0x3a26, 0x7f},
+ {0x3a28, 0x3f},
+};
+
+static const struct imx335_reg mipi_data_rate_891Mbps[] = {
+ {0x300c, 0x3b},
+ {0x300d, 0x2a},
+ {0x314c, 0x29},
+ {0x314d, 0x01},
+ {0x315a, 0x06},
+ {0x3168, 0xa0},
+ {0x316a, 0x7e},
+ {0x319e, 0x02},
+ {0x3a18, 0x7f},
+ {0x3a1a, 0x37},
+ {0x3a1c, 0x37},
+ {0x3a1e, 0xf7},
+ {0x3a20, 0x3f},
+ {0x3a22, 0x6f},
+ {0x3a24, 0x3f},
+ {0x3a26, 0x5f},
+ {0x3a28, 0x2f},
+};
+
+static const s64 link_freq[] = {
+ /* Corresponds to 1188Mbps data lane rate */
+ IMX335_LINK_FREQ_594MHz,
+ /* Corresponds to 891Mbps data lane rate */
+ IMX335_LINK_FREQ_445MHz,
+};
+
+static const struct imx335_reg_list link_freq_reglist[] = {
+ {
+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_1188Mbps),
+ .regs = mipi_data_rate_1188Mbps,
+ },
+ {
+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_891Mbps),
+ .regs = mipi_data_rate_891Mbps,
+ },
+};
+
static const u32 imx335_mbus_codes[] = {
MEDIA_BUS_FMT_SRGGB12_1X12,
MEDIA_BUS_FMT_SRGGB10_1X10,
@@ -280,7 +331,6 @@ static const struct imx335_mode supported_mode = {
.vblank_min = 2560,
.vblank_max = 133060,
.pclk = 396000000,
- .link_freq_idx = 0,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2592x1940_regs),
.regs = mode_2592x1940_regs,
@@ -405,7 +455,7 @@ static int imx335_update_controls(struct imx335 *imx335,
{
int ret;
- ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, mode->link_freq_idx);
+ ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, imx335->link_freq_idx);
if (ret)
return ret;
@@ -755,6 +805,14 @@ static int imx335_start_streaming(struct imx335 *imx335)
const struct imx335_reg_list *reg_list;
int ret;
+ /* Setup PLL */
+ reg_list = &link_freq_reglist[imx335->link_freq_idx];
+ ret = imx335_write_regs(imx335, reg_list->regs, reg_list->num_of_regs);
+ if (ret) {
+ dev_err(imx335->dev, "%s failed to set plls\n", __func__);
+ return ret;
+ }
+
/* Write sensor mode registers */
reg_list = &imx335->cur_mode->reg_list;
ret = imx335_write_regs(imx335, reg_list->regs,
@@ -881,7 +939,7 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
};
struct fwnode_handle *ep;
unsigned long rate;
- unsigned int i;
+ unsigned int i, j;
int ret;
if (!fwnode)
@@ -945,13 +1003,21 @@ static int imx335_parse_hw_config(struct imx335 *imx335)
goto done_endpoint_free;
}
- for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
- if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ)
- goto done_endpoint_free;
- dev_err(imx335->dev, "no compatible link frequencies found\n");
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ for (j = 0; j < ARRAY_SIZE(link_freq); j++) {
+ if (bus_cfg.link_frequencies[i] == link_freq[j]) {
+ imx335->link_freq_idx = j;
+ break;
+ }
+ }
- ret = -EINVAL;
+ if (j == ARRAY_SIZE(link_freq)) {
+ ret = dev_err_probe(imx335->dev, -EINVAL,
+ "no supported link freq found\n");
+ goto done_endpoint_free;
+ }
+ }
done_endpoint_free:
v4l2_fwnode_endpoint_free(&bus_cfg);
@@ -1101,7 +1167,7 @@ static int imx335_init_controls(struct imx335 *imx335)
V4L2_CID_LINK_FREQ,
ARRAY_SIZE(link_freq) -
1,
- mode->link_freq_idx,
+ imx335->link_freq_idx,
link_freq);
if (imx335->link_freq_ctrl)
imx335->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;