Thomas Gleixner | c942fdd | 2019-05-27 08:55:06 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 2 | /* |
| 3 | * cx18 ioctl control functions |
| 4 | * |
| 5 | * Derived from ivtv-controls.c |
| 6 | * |
| 7 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 8 | */ |
Andy Walls | 225aeb1 | 2009-07-23 21:51:29 -0300 | [diff] [blame] | 9 | #include <linux/kernel.h> |
Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 10 | #include <linux/slab.h> |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 11 | |
| 12 | #include "cx18-driver.h" |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 13 | #include "cx18-cards.h" |
| 14 | #include "cx18-ioctl.h" |
| 15 | #include "cx18-audio.h" |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 16 | #include "cx18-mailbox.h" |
| 17 | #include "cx18-controls.h" |
| 18 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 19 | static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 20 | { |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 21 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); |
| 22 | int type = cxhdl->stream_type->val; |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 23 | |
Hans Verkuil | 31554ae | 2008-05-25 11:21:27 -0300 | [diff] [blame] | 24 | if (atomic_read(&cx->ana_capturing) > 0) |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 25 | return -EBUSY; |
| 26 | |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 27 | if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || |
Andy Walls | 0c62925 | 2009-04-26 16:34:36 -0300 | [diff] [blame] | 28 | !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS || |
| 29 | type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD || |
| 30 | type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) { |
| 31 | /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */ |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 32 | cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; |
Mauro Carvalho Chehab | 6beb138 | 2016-10-18 17:44:03 -0200 | [diff] [blame] | 33 | CX18_DEBUG_INFO("disabled insertion of sliced VBI data into the MPEG stream\n"); |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 34 | return 0; |
| 35 | } |
| 36 | |
| 37 | /* Allocate sliced VBI buffers if needed. */ |
| 38 | if (cx->vbi.sliced_mpeg_data[0] == NULL) { |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 39 | int i; |
| 40 | |
| 41 | for (i = 0; i < CX18_VBI_FRAMES; i++) { |
Andy Walls | 302df97 | 2009-01-31 00:33:02 -0300 | [diff] [blame] | 42 | cx->vbi.sliced_mpeg_data[i] = |
| 43 | kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 44 | if (cx->vbi.sliced_mpeg_data[i] == NULL) { |
| 45 | while (--i >= 0) { |
| 46 | kfree(cx->vbi.sliced_mpeg_data[i]); |
| 47 | cx->vbi.sliced_mpeg_data[i] = NULL; |
| 48 | } |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 49 | cx->vbi.insert_mpeg = |
| 50 | V4L2_MPEG_STREAM_VBI_FMT_NONE; |
Mauro Carvalho Chehab | 6beb138 | 2016-10-18 17:44:03 -0200 | [diff] [blame] | 51 | CX18_WARN("Unable to allocate buffers for sliced VBI data insertion\n"); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 52 | return -ENOMEM; |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | cx->vbi.insert_mpeg = fmt; |
Mauro Carvalho Chehab | 6beb138 | 2016-10-18 17:44:03 -0200 | [diff] [blame] | 58 | CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,when sliced VBI is enabled\n"); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 59 | |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 60 | /* |
| 61 | * If our current settings have no lines set for capture, store a valid, |
| 62 | * default set of service lines to capture, in our current settings. |
| 63 | */ |
Mauro Carvalho Chehab | aed6abd | 2008-04-29 21:38:51 -0300 | [diff] [blame] | 64 | if (cx18_get_service_set(cx->vbi.sliced_in) == 0) { |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 65 | if (cx->is_60hz) |
Andy Walls | 49a5375 | 2009-03-01 23:10:07 -0300 | [diff] [blame] | 66 | cx->vbi.sliced_in->service_set = |
| 67 | V4L2_SLICED_CAPTION_525; |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 68 | else |
| 69 | cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; |
Mauro Carvalho Chehab | aed6abd | 2008-04-29 21:38:51 -0300 | [diff] [blame] | 70 | cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 71 | } |
| 72 | return 0; |
| 73 | } |
| 74 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 75 | static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val) |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 76 | { |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 77 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); |
| 78 | int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; |
Hans Verkuil | ebf984b | 2015-04-09 04:05:59 -0300 | [diff] [blame] | 79 | struct v4l2_subdev_format format = { |
| 80 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, |
| 81 | }; |
| 82 | struct v4l2_mbus_framefmt *fmt = &format.format; |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 83 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 84 | /* fix videodecoder resolution */ |
Hans Verkuil | ebf984b | 2015-04-09 04:05:59 -0300 | [diff] [blame] | 85 | fmt->width = cxhdl->width / (is_mpeg1 ? 2 : 1); |
| 86 | fmt->height = cxhdl->height; |
| 87 | fmt->code = MEDIA_BUS_FMT_FIXED; |
| 88 | v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format); |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 89 | return 0; |
Andy Walls | 3b6fe58f | 2008-06-21 08:36:31 -0300 | [diff] [blame] | 90 | } |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 91 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 92 | static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) |
Andy Walls | 3b6fe58f | 2008-06-21 08:36:31 -0300 | [diff] [blame] | 93 | { |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 94 | static const u32 freqs[3] = { 44100, 48000, 32000 }; |
| 95 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 96 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 97 | /* The audio clock of the digitizer must match the codec sample |
| 98 | rate otherwise you get some very strange effects. */ |
| 99 | if (idx < ARRAY_SIZE(freqs)) |
| 100 | cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); |
| 101 | return 0; |
Andy Walls | 3b6fe58f | 2008-06-21 08:36:31 -0300 | [diff] [blame] | 102 | } |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 103 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 104 | static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) |
Andy Walls | 3b6fe58f | 2008-06-21 08:36:31 -0300 | [diff] [blame] | 105 | { |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 106 | struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl); |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 107 | |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 108 | cx->dualwatch_stereo_mode = val; |
| 109 | return 0; |
Hans Verkuil | 1c1e45d | 2008-04-28 20:24:33 -0300 | [diff] [blame] | 110 | } |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 111 | |
Julia Lawall | 083206fc | 2015-11-22 15:44:38 -0200 | [diff] [blame] | 112 | const struct cx2341x_handler_ops cx18_cxhdl_ops = { |
Hans Verkuil | a75b9be | 2010-12-31 10:22:52 -0300 | [diff] [blame] | 113 | .s_audio_mode = cx18_s_audio_mode, |
| 114 | .s_audio_sampling_freq = cx18_s_audio_sampling_freq, |
| 115 | .s_video_encoding = cx18_s_video_encoding, |
| 116 | .s_stream_vbi_fmt = cx18_s_stream_vbi_fmt, |
| 117 | }; |