diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 04:45:08 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 04:45:08 +0300 |
commit | 73d21a3579818aa0e39de207474a39ca35c7d8cb (patch) | |
tree | ae723d1026a6f39aa22bbcb3e82d3966ac7f5dcc /drivers/media/i2c/tda1997x.c | |
parent | 6f2b76a4a384e05ac8d3349831f29dff5de1e1e2 (diff) | |
parent | 57c3b9f55ba875a6f6295fa59f0bdc0a01c544f8 (diff) | |
download | linux-73d21a3579818aa0e39de207474a39ca35c7d8cb.tar.xz |
Merge tag 'media/v5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- New driver for SK Hynix Hi-846 8M pixel camera
- New driver for the ov13b10 camera
- New driver for Renesas R-Car ISP
- mtk-vcodec gained support for version 2 of decoder firmware ABI
- The legacy sir_ir driver got removed
- videobuf2: the vb2_mem_ops kAPI had some improvements
- lots of cleanups, fixes and new features at device drivers
* tag 'media/v5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (328 commits)
media: venus: core: Add sdm660 DT compatible and resource struct
media: dt-bindings: media: venus: Add sdm660 dt schema
media: venus: vdec: decoded picture buffer handling during reconfig sequence
media: venus: Handle fatal errors during encoding and decoding
media: venus: helpers: Add helper to mark fatal vb2 error
media: venus: hfi: Check for sys error on session hfi functions
media: venus: Make sys_error flag an atomic bitops
media: venus: venc: Use pmruntime autosuspend
media: allegro: write vui parameters for HEVC
media: allegro: nal-hevc: implement generator for vui
media: allegro: write correct colorspace into SPS
media: allegro: extract nal value lookup functions to header
media: allegro: correctly scale the bit rate in SPS
media: allegro: remove external QP table
media: allegro: fix row and column in response message
media: allegro: add control to disable encoder buffer
media: allegro: add encoder buffer support
media: allegro: add pm_runtime support
media: allegro: lookup VCU settings
media: allegro: fix module removal if initialization failed
...
Diffstat (limited to 'drivers/media/i2c/tda1997x.c')
-rw-r--r-- | drivers/media/i2c/tda1997x.c | 131 |
1 files changed, 73 insertions, 58 deletions
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 6070aaf0b32e..8fafce26d62f 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -1092,67 +1092,82 @@ tda1997x_detect_std(struct tda1997x_state *state, struct v4l2_dv_timings *timings) { struct v4l2_subdev *sd = &state->sd; - u32 vper; - u16 hper; - u16 hsper; - int i; /* * Read the FMT registers - * REG_V_PER: Period of a frame (or two fields) in MCLK(27MHz) cycles - * REG_H_PER: Period of a line in MCLK(27MHz) cycles - * REG_HS_WIDTH: Period of horiz sync pulse in MCLK(27MHz) cycles + * REG_V_PER: Period of a frame (or field) in MCLK (27MHz) cycles + * REG_H_PER: Period of a line in MCLK (27MHz) cycles + * REG_HS_WIDTH: Period of horiz sync pulse in MCLK (27MHz) cycles */ - vper = io_read24(sd, REG_V_PER) & MASK_VPER; - hper = io_read16(sd, REG_H_PER) & MASK_HPER; - hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH; - v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper); + u32 vper, vsync_pos; + u16 hper, hsync_pos, hsper, interlaced; + u16 htot, hact, hfront, hsync, hback; + u16 vtot, vact, vfront1, vfront2, vsync, vback1, vback2; if (!state->input_detect[0] && !state->input_detect[1]) return -ENOLINK; - for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) { - const struct v4l2_bt_timings *bt; - u32 lines, width, _hper, _hsper; - u32 vmin, vmax, hmin, hmax, hsmin, hsmax; - bool vmatch, hmatch, hsmatch; - - bt = &v4l2_dv_timings_presets[i].bt; - width = V4L2_DV_BT_FRAME_WIDTH(bt); - lines = V4L2_DV_BT_FRAME_HEIGHT(bt); - _hper = (u32)bt->pixelclock / width; - if (bt->interlaced) - lines /= 2; - /* vper +/- 0.7% */ - vmin = ((27000000 / 1000) * 993) / _hper * lines; - vmax = ((27000000 / 1000) * 1007) / _hper * lines; - /* hper +/- 1.0% */ - hmin = ((27000000 / 100) * 99) / _hper; - hmax = ((27000000 / 100) * 101) / _hper; - /* hsper +/- 2 (take care to avoid 32bit overflow) */ - _hsper = 27000 * bt->hsync / ((u32)bt->pixelclock/1000); - hsmin = _hsper - 2; - hsmax = _hsper + 2; - - /* vmatch matches the framerate */ - vmatch = ((vper <= vmax) && (vper >= vmin)) ? 1 : 0; - /* hmatch matches the width */ - hmatch = ((hper <= hmax) && (hper >= hmin)) ? 1 : 0; - /* hsmatch matches the hswidth */ - hsmatch = ((hsper <= hsmax) && (hsper >= hsmin)) ? 1 : 0; - if (hmatch && vmatch && hsmatch) { - v4l2_print_dv_timings(sd->name, "Detected format: ", - &v4l2_dv_timings_presets[i], - false); - if (timings) - *timings = v4l2_dv_timings_presets[i]; - return 0; - } - } + vper = io_read24(sd, REG_V_PER); + hper = io_read16(sd, REG_H_PER); + hsper = io_read16(sd, REG_HS_WIDTH); + vsync_pos = vper & MASK_VPER_SYNC_POS; + hsync_pos = hper & MASK_HPER_SYNC_POS; + interlaced = hsper & MASK_HSWIDTH_INTERLACED; + vper &= MASK_VPER; + hper &= MASK_HPER; + hsper &= MASK_HSWIDTH; + v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper); + + htot = io_read16(sd, REG_FMT_H_TOT); + hact = io_read16(sd, REG_FMT_H_ACT); + hfront = io_read16(sd, REG_FMT_H_FRONT); + hsync = io_read16(sd, REG_FMT_H_SYNC); + hback = io_read16(sd, REG_FMT_H_BACK); + + vtot = io_read16(sd, REG_FMT_V_TOT); + vact = io_read16(sd, REG_FMT_V_ACT); + vfront1 = io_read(sd, REG_FMT_V_FRONT_F1); + vfront2 = io_read(sd, REG_FMT_V_FRONT_F2); + vsync = io_read(sd, REG_FMT_V_SYNC); + vback1 = io_read(sd, REG_FMT_V_BACK_F1); + vback2 = io_read(sd, REG_FMT_V_BACK_F2); + + v4l2_dbg(1, debug, sd, "Geometry: H %u %u %u %u %u Sync%c V %u %u %u %u %u %u %u Sync%c\n", + htot, hact, hfront, hsync, hback, hsync_pos ? '+' : '-', + vtot, vact, vfront1, vfront2, vsync, vback1, vback2, vsync_pos ? '+' : '-'); + + if (!timings) + return 0; - v4l_err(state->client, "no resolution match for timings: %d/%d/%d\n", - vper, hper, hsper); - return -ERANGE; + timings->type = V4L2_DV_BT_656_1120; + timings->bt.width = hact; + timings->bt.hfrontporch = hfront; + timings->bt.hsync = hsync; + timings->bt.hbackporch = hback; + timings->bt.height = vact; + timings->bt.vfrontporch = vfront1; + timings->bt.vsync = vsync; + timings->bt.vbackporch = vback1; + timings->bt.interlaced = interlaced ? V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; + timings->bt.polarities = vsync_pos ? V4L2_DV_VSYNC_POS_POL : 0; + timings->bt.polarities |= hsync_pos ? V4L2_DV_HSYNC_POS_POL : 0; + + timings->bt.pixelclock = (u64)htot * vtot * 27000000; + if (interlaced) { + timings->bt.il_vfrontporch = vfront2; + timings->bt.il_vsync = timings->bt.vsync; + timings->bt.il_vbackporch = vback2; + do_div(timings->bt.pixelclock, vper * 2 /* full frame */); + } else { + timings->bt.il_vfrontporch = 0; + timings->bt.il_vsync = 0; + timings->bt.il_vbackporch = 0; + do_div(timings->bt.pixelclock, vper); + } + v4l2_find_dv_timings_cap(timings, &tda1997x_dv_timings_cap, + (u32)timings->bt.pixelclock / 500, NULL, NULL); + v4l2_print_dv_timings(sd->name, "Detected format: ", timings, false); + return 0; } /* some sort of errata workaround for chip revision 0 (N1) */ @@ -1248,13 +1263,13 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) { struct v4l2_subdev *sd = &state->sd; union hdmi_infoframe frame; - u8 buffer[40]; + u8 buffer[40] = { 0 }; u8 reg; int len, err; /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); - err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); + err = hdmi_infoframe_unpack(&frame, buffer, len); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", @@ -1928,13 +1943,13 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr) { struct tda1997x_state *state = to_state(sd); union hdmi_infoframe frame; - u8 buffer[40]; + u8 buffer[40] = { 0 }; int len, err; /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); - err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); + err = hdmi_infoframe_unpack(&frame, buffer, len); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", @@ -2450,7 +2465,8 @@ static const struct media_entity_operations tda1997x_media_ops = { static int tda1997x_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct tda1997x_state *state = snd_soc_dai_get_drvdata(dai); + struct v4l2_subdev *sd = snd_soc_dai_get_drvdata(dai); + struct tda1997x_state *state = to_state(sd); struct snd_soc_component *component = dai->component; struct snd_pcm_runtime *rtd = substream->runtime; int rate, err; @@ -2759,7 +2775,6 @@ static int tda1997x_probe(struct i2c_client *client, dev_err(&client->dev, "register audio codec failed\n"); goto err_free_media; } - dev_set_drvdata(&state->client->dev, state); v4l_info(state->client, "registered audio codec\n"); } |