Skip to content

Commit c86beee

Browse files
committed
media: imx708: Compute link frequency PLL settings
Rather than the 3 hard coded PLL settings for 447, 450, and 453MHz, compute the PLL settings based on device tree. Signed-off-by: Dave Stevenson <[email protected]>
1 parent 81e6a84 commit c86beee

File tree

1 file changed

+50
-75
lines changed

1 file changed

+50
-75
lines changed

drivers/media/i2c/imx708.c

Lines changed: 50 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,22 @@ MODULE_PARM_DESC(qbc_adjust, "Quad Bayer broken line correction strength [0,2-5]
3737
#define IMX708_MODE_STANDBY 0x00
3838
#define IMX708_MODE_STREAMING 0x01
3939

40-
#define IMX708_EXCLK_FREQ 0x18
41-
4240
#define IMX708_REG_ORIENTATION CCI_REG8(0x101)
4341

42+
#define IMX708_REG_EXCK_FREQ CCI_REG16(0x0136)
43+
#define IMX708_EXCLK_FREQ 0x1800
4444
#define IMX708_INCLK_FREQ 24000000
4545

46+
#define IMX708_REG_IVT_PREDIV CCI_REG8(0x0305)
47+
#define IMX708_IVT_PREDIV 0x02
48+
#define IMX708_REG_IVT_MPY CCI_REG16(0x0306)
49+
50+
#define IMX708_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
51+
#define IMX708_IOP_SYSCK_DIV 0x02
52+
#define IMX708_REG_IOP_PREDIV CCI_REG8(0x030d)
53+
#define IMX708_IOP_PREDIV 0x04
54+
#define IMX708_REG_IOP_MPY CCI_REG16(0x030e)
55+
4656
/* Default initial pixel rate, will get updated for each mode. */
4757
#define IMX708_INITIAL_PIXEL_RATE 590000000
4858

@@ -194,56 +204,14 @@ static const u8 pdaf_gains[2][9] = {
194204
{ 0x36, 0x36, 0x36, 0x39, 0x3e, 0x46, 0x4c, 0x4c, 0x4c }
195205
};
196206

197-
/* Link frequency setup */
198-
enum {
199-
IMX708_LINK_FREQ_450MHZ,
200-
IMX708_LINK_FREQ_447MHZ,
201-
IMX708_LINK_FREQ_453MHZ,
202-
};
203-
204-
static const s64 link_freqs[] = {
205-
[IMX708_LINK_FREQ_450MHZ] = 450000000,
206-
[IMX708_LINK_FREQ_447MHZ] = 447000000,
207-
[IMX708_LINK_FREQ_453MHZ] = 453000000,
208-
};
209-
210-
/* 450MHz is the nominal "default" link frequency */
211-
static const struct cci_reg_sequence link_450Mhz_regs[] = {
212-
{CCI_REG8(0x030E), 0x01},
213-
{CCI_REG8(0x030F), 0x2c},
214-
};
215-
216-
static const struct cci_reg_sequence link_447Mhz_regs[] = {
217-
{CCI_REG8(0x030E), 0x01},
218-
{CCI_REG8(0x030F), 0x2a},
219-
};
220-
221-
static const struct cci_reg_sequence link_453Mhz_regs[] = {
222-
{CCI_REG8(0x030E), 0x01},
223-
{CCI_REG8(0x030F), 0x2e},
224-
};
225-
226-
static const struct imx708_reg_list link_freq_regs[] = {
227-
[IMX708_LINK_FREQ_450MHZ] = {
228-
.regs = link_450Mhz_regs,
229-
.num_of_regs = ARRAY_SIZE(link_450Mhz_regs)
230-
},
231-
[IMX708_LINK_FREQ_447MHZ] = {
232-
.regs = link_447Mhz_regs,
233-
.num_of_regs = ARRAY_SIZE(link_447Mhz_regs)
234-
},
235-
[IMX708_LINK_FREQ_453MHZ] = {
236-
.regs = link_453Mhz_regs,
237-
.num_of_regs = ARRAY_SIZE(link_453Mhz_regs)
238-
},
239-
};
240-
241207
static const struct cci_reg_sequence mode_common_regs[] = {
242208
{CCI_REG8(0x0100), 0x00},
243-
{CCI_REG8(0x0136), IMX708_EXCLK_FREQ}, //REG_EXCK_FREQ_MSB
244-
{CCI_REG8(0x0137), 0x00}, //REG_EXCK_FREQ_LSB
245-
{CCI_REG8(0x33F0), 0x02}, //REG_IOPSYCK_DIV
246-
{CCI_REG8(0x33F1), 0x05}, //REG_IOPPXCK_DIV
209+
{IMX708_REG_EXCK_FREQ, IMX708_EXCLK_FREQ},
210+
{CCI_REG8(0x33F0), 0x02},
211+
{CCI_REG8(0x33F1), 0x05},
212+
{IMX708_REG_IVT_PREDIV, IMX708_IVT_PREDIV},
213+
{IMX708_REG_IOP_SYSCK_DIV, IMX708_IOP_SYSCK_DIV},
214+
{IMX708_REG_IOP_PREDIV, IMX708_IOP_PREDIV},
247215
{CCI_REG8(0x3062), 0x00},
248216
{CCI_REG8(0x3063), 0x12},
249217
{CCI_REG8(0x3068), 0x00},
@@ -328,11 +296,8 @@ static const struct cci_reg_sequence mode_4608x2592_regs[] = {
328296
{CCI_REG8(0x034F), 0x20},
329297
{CCI_REG8(0x0301), 0x05},
330298
{CCI_REG8(0x0303), 0x02},
331-
{CCI_REG8(0x0305), 0x02},
332299
{CCI_REG8(0x0306), 0x00},
333300
{CCI_REG8(0x0307), 0x7C},
334-
{CCI_REG8(0x030B), 0x02},
335-
{CCI_REG8(0x030D), 0x04},
336301
{CCI_REG8(0x0310), 0x01},
337302
{CCI_REG8(0x3CA0), 0x00},
338303
{CCI_REG8(0x3CA1), 0x64},
@@ -414,11 +379,8 @@ static const struct cci_reg_sequence mode_2x2binned_regs[] = {
414379
{CCI_REG8(0x034F), 0x10},
415380
{CCI_REG8(0x0301), 0x05},
416381
{CCI_REG8(0x0303), 0x02},
417-
{CCI_REG8(0x0305), 0x02},
418382
{CCI_REG8(0x0306), 0x00},
419383
{CCI_REG8(0x0307), 0x7A},
420-
{CCI_REG8(0x030B), 0x02},
421-
{CCI_REG8(0x030D), 0x04},
422384
{CCI_REG8(0x0310), 0x01},
423385
{CCI_REG8(0x3CA0), 0x00},
424386
{CCI_REG8(0x3CA1), 0x3C},
@@ -500,11 +462,8 @@ static const struct cci_reg_sequence mode_2x2binned_720p_regs[] = {
500462
{CCI_REG8(0x034F), 0x60},
501463
{CCI_REG8(0x0301), 0x05},
502464
{CCI_REG8(0x0303), 0x02},
503-
{CCI_REG8(0x0305), 0x02},
504465
{CCI_REG8(0x0306), 0x00},
505466
{CCI_REG8(0x0307), 0x76},
506-
{CCI_REG8(0x030B), 0x02},
507-
{CCI_REG8(0x030D), 0x04},
508467
{CCI_REG8(0x0310), 0x01},
509468
{CCI_REG8(0x3CA0), 0x00},
510469
{CCI_REG8(0x3CA1), 0x3C},
@@ -586,11 +545,8 @@ static const struct cci_reg_sequence mode_hdr_regs[] = {
586545
{CCI_REG8(0x034F), 0x10},
587546
{CCI_REG8(0x0301), 0x05},
588547
{CCI_REG8(0x0303), 0x02},
589-
{CCI_REG8(0x0305), 0x02},
590548
{CCI_REG8(0x0306), 0x00},
591549
{CCI_REG8(0x0307), 0xA2},
592-
{CCI_REG8(0x030B), 0x02},
593-
{CCI_REG8(0x030D), 0x04},
594550
{CCI_REG8(0x0310), 0x01},
595551
{CCI_REG8(0x3CA0), 0x00},
596552
{CCI_REG8(0x3CA1), 0x00},
@@ -832,7 +788,8 @@ struct imx708 {
832788
/* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
833789
unsigned int long_exp_shift;
834790

835-
unsigned int link_freq_idx;
791+
s64 link_freq_value;
792+
u16 iop_pll_mpy;
836793
};
837794

838795
static inline struct imx708 *to_imx708(struct v4l2_subdev *_sd)
@@ -1367,7 +1324,7 @@ static int imx708_get_selection(struct v4l2_subdev *sd,
13671324
static int imx708_start_streaming(struct imx708 *imx708)
13681325
{
13691326
struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
1370-
const struct imx708_reg_list *reg_list, *freq_regs;
1327+
const struct imx708_reg_list *reg_list;
13711328
int i, ret;
13721329
u64 val;
13731330

@@ -1413,11 +1370,10 @@ static int imx708_start_streaming(struct imx708 *imx708)
14131370
}
14141371

14151372
/* Update the link frequency registers */
1416-
freq_regs = &link_freq_regs[imx708->link_freq_idx];
1417-
ret = cci_multi_reg_write(imx708->regmap, freq_regs->regs,
1418-
freq_regs->num_of_regs, NULL);
1373+
ret = cci_write(imx708->regmap, IMX708_REG_IOP_MPY, imx708->iop_pll_mpy,
1374+
NULL);
14191375
if (ret) {
1420-
dev_err(&client->dev, "%s failed to set link frequency registers\n",
1376+
dev_err(&client->dev, "%s failed to set link frequency register\n",
14211377
__func__);
14221378
return ret;
14231379
}
@@ -1706,7 +1662,7 @@ static int imx708_init_controls(struct imx708 *imx708)
17061662

17071663
ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx708_ctrl_ops,
17081664
V4L2_CID_LINK_FREQ, 0, 0,
1709-
&link_freqs[imx708->link_freq_idx]);
1665+
&imx708->link_freq_value);
17101666
if (ctrl)
17111667
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
17121668

@@ -1807,6 +1763,25 @@ static void imx708_free_controls(struct imx708 *imx708)
18071763
mutex_destroy(&imx708->mutex);
18081764
}
18091765

1766+
static int imx708_check_link_freq(s64 link_frequency, u16 *mpy_out)
1767+
{
1768+
s64 mpy = link_frequency * 2 * IMX708_IOP_SYSCK_DIV * IMX708_IOP_PREDIV;
1769+
s64 tmp;
1770+
1771+
mpy = do_div(mpy, IMX708_INCLK_FREQ);
1772+
1773+
tmp = mpy * (IMX708_INCLK_FREQ / IMX708_IOP_PREDIV);
1774+
do_div(tmp, IMX708_IOP_SYSCK_DIV / 2);
1775+
1776+
if (tmp != link_frequency)
1777+
return -EINVAL;
1778+
1779+
if (mpy_out)
1780+
*mpy_out = mpy;
1781+
1782+
return 0;
1783+
}
1784+
18101785
static int imx708_check_hwcfg(struct device *dev, struct imx708 *imx708)
18111786
{
18121787
struct fwnode_handle *endpoint;
@@ -1839,16 +1814,16 @@ static int imx708_check_hwcfg(struct device *dev, struct imx708 *imx708)
18391814
goto error_out;
18401815
}
18411816

1842-
for (i = 0; i < ARRAY_SIZE(link_freqs); i++) {
1843-
if (link_freqs[i] == ep_cfg.link_frequencies[0]) {
1844-
imx708->link_freq_idx = i;
1817+
for (i = 0; i < ep_cfg.nr_of_link_frequencies; i++) {
1818+
if (!imx708_check_link_freq(ep_cfg.link_frequencies[i],
1819+
&imx708->iop_pll_mpy)) {
1820+
imx708->link_freq_value = ep_cfg.link_frequencies[i];
18451821
break;
18461822
}
18471823
}
18481824

1849-
if (i == ARRAY_SIZE(link_freqs)) {
1850-
dev_err(dev, "Link frequency not supported: %lld\n",
1851-
ep_cfg.link_frequencies[0]);
1825+
if (i == ep_cfg.nr_of_link_frequencies) {
1826+
dev_err(dev, "No link frequencies supported\n");
18521827
ret = -EINVAL;
18531828
goto error_out;
18541829
}

0 commit comments

Comments
 (0)