Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp3471668imm; Tue, 17 Jul 2018 05:31:42 -0700 (PDT) X-Google-Smtp-Source: AAOMgpd4bHZM4idhv/V+JSa0vOAC7dQwXUDPf9unvXY1WtUEmCX2xhsIMmaJC0cKQU/kxMfgta5F X-Received: by 2002:a17:902:694a:: with SMTP id k10-v6mr1481205plt.166.1531830702914; Tue, 17 Jul 2018 05:31:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531830702; cv=none; d=google.com; s=arc-20160816; b=cfVUOB+br2JlVyCc46fKcLVEuYb9IIhbfXG6tLrOMkTXGpRwF01t6LJY3Xytcrlyc6 8hCJ0tEnR3Hq1vSL2o4FbOkWggkHq4iCCGFF6UVJG/cmfXONgza05io+UbCP8BTGPvuK IDJC1RBG0IPCrYGwV2DqKYhWdxXtL9DHoebeRfDcjHd/yJdl5XqOKFRx7P24DnIxF4Ny N1d2vP6tMLbYopmDiXgFnS8Ks/g9jC42W7RAObU5Ry8EeaVYmn48nFvYYGr68+Qb6aqi 6kl1TLejc+M+O/mvfVth3UhetXudxQjApMmFRojL2mIV6CcNdbddF5u8nsOUXbnL1r5S K5BQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:arc-authentication-results; bh=vY8HYn1HszAVwe8TG2m/k40DAj5BXD47/3Ah/f8+cnk=; b=UfU/2M+t9N5V1EBQAQXALgq64yZmX6wyD9JdRlqYuUxwN4EaH2SCAdiyfTEpCf4dgu b8gY57yv64GM6A6eRdSa0h8vf7bb6DEQ/VIPaj7fXWmp7fXQg3/rhUi/KHPy2saM/yZi 8sIAO75YoGabtPqy9sUmmKJFFN9M4/29Rvl8/AgTySNg2RyjtldCir4cHAU+XxkcQ+BX QX5fV4ewjOw6p4u3CFw/aDvGl7IvQpvanuNehIdnfV4Wt9vP4zU9cbU4ogE1wjuCFgLR efWgm8PRgpnn7fph8PicwRqEgTgqeddBCSddoXi4pVAVx/lNeS1tYptTlUNEsDQeqoL/ b5Tg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n16-v6si716541pgl.596.2018.07.17.05.31.28; Tue, 17 Jul 2018 05:31:42 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731608AbeGQNCS (ORCPT + 99 others); Tue, 17 Jul 2018 09:02:18 -0400 Received: from lb2-smtp-cloud8.xs4all.net ([194.109.24.25]:52618 "EHLO lb2-smtp-cloud8.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728515AbeGQNCS (ORCPT ); Tue, 17 Jul 2018 09:02:18 -0400 Received: from [IPv6:2001:983:e9a7:1:4d0:88d5:cbb8:db75] ([IPv6:2001:983:e9a7:1:4d0:88d5:cbb8:db75]) by smtp-cloud8.xs4all.net with ESMTPA id fP6zfZE7joj71fP70fzGd3; Tue, 17 Jul 2018 14:29:50 +0200 Subject: Re: [PATCH v7 3/6] cx25840: add pin to pad mapping and output format configuration To: "Maciej S. Szmigiero" Cc: Michael Krufky , Mauro Carvalho Chehab , Andy Walls , linux-kernel , linux-media@vger.kernel.org References: <984fbf6359a896f156ddf64b1fb8211c3cca54e3.1530565770.git.mail@maciej.szmigiero.name> <3421f58a-3a60-28f1-830c-66f5d1bf5517@xs4all.nl> From: Hans Verkuil Message-ID: <718c9066-07f0-2b80-f2eb-4f7681b6c9cd@xs4all.nl> Date: Tue, 17 Jul 2018 14:29:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4wfPBPLa6JcRR/50ZHz2XP0Gng0xUx14Bmdtwz9F9bDROmevOpHKhUiBjTvDv367TV92iZ7GptnCApYdacU41r1+9/ebxf8ZvZcLkfcVF42wO8xn3G7DxE xOwP/CP/2cn2Cznh3eJtJT9FW96TGazR1YJ+gggSscereotvYl+f8vDreWla1fdzcLeT8zQ4bMPyCmHTdu0Orql7qng1bw0QzZowJp50/t7lqcWJEiEmOsnk pIFM/86BD6gysE/YLxduZo6WQ9VEvx4Tu86UgPIhUi5DwRt+uWx6G0oWssS5nZJu9mUWF4D4B3rPPAjqZT1M8gsXzOg8bXgjNcyaYs/Qe4I8qz1RsOpB+y7M 9s4+d+5psDiDPL3cQYwsjIVOdnifsTM6UtRr6JiGX7MWOFmHvP3rA+B0f0YZik4ZncsNb6gwsoz2zOC7hhDooiXqIbRbPVpUsEo+qJ3BRpnXJGKuWzM= Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 10/07/18 23:47, Maciej S. Szmigiero wrote: > Hi Hans, > > On 04.07.2018 11:05, Hans Verkuil wrote: >> On 02/07/18 23:23, Maciej S. Szmigiero wrote: > (..) >>> @@ -316,6 +319,260 @@ static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n, >>> return 0; >>> } >>> >>> +static u8 cx25840_function_to_pad(struct i2c_client *client, u8 function) >>> +{ >>> + switch (function) { >>> + case CX25840_PAD_ACTIVE: >>> + return 1; >>> + >>> + case CX25840_PAD_VACTIVE: >>> + return 2; >>> + >>> + case CX25840_PAD_CBFLAG: >>> + return 3; >>> + >>> + case CX25840_PAD_VID_DATA_EXT0: >>> + return 4; >>> + >>> + case CX25840_PAD_VID_DATA_EXT1: >>> + return 5; >>> + >>> + case CX25840_PAD_GPO0: >>> + return 6; >>> + >>> + case CX25840_PAD_GPO1: >>> + return 7; >>> + >>> + case CX25840_PAD_GPO2: >>> + return 8; >>> + >>> + case CX25840_PAD_GPO3: >>> + return 9; >>> + >>> + case CX25840_PAD_IRQ_N: >>> + return 10; >>> + >>> + case CX25840_PAD_AC_SYNC: >>> + return 11; >>> + >>> + case CX25840_PAD_AC_SDOUT: >>> + return 12; >>> + >>> + case CX25840_PAD_PLL_CLK: >>> + return 13; >>> + >>> + case CX25840_PAD_VRESET: >>> + return 14; >>> + >>> + default: >>> + if (function != CX25840_PAD_DEFAULT) >>> + v4l_err(client, >>> + "invalid function %u, assuming default\n", >>> + (unsigned int)function); >>> + return 0; >>> + } >> >> Unless I am mistaken this function boils down to: >> >> static u8 cx25840_function_to_pad(struct i2c_client *client, u8 function) >> { >> return function > CX25840_PAD_VRESET ? 0 : function; >> } > > Yes, you are right these functions are equivalent (sans a warning when > a caller passes an invalid function). > > However, these values (CX25840_PAD_*) were meant to be driver-internal. > If we use them also as register value constants (which is what > cx25840_function_to_pad() is supposed to return) then we'll need to add > a comment to their enum cx25840_io_pad so nobody shuffles them or changes > their values by mistake. Right. Just add a comment and keep it simple. > >>> @@ -1647,6 +1924,119 @@ static void log_audio_status(struct i2c_client *client) >>> } >>> } >>> >>> +#define CX25840_VCONFIG_OPTION(state, cfg_in, opt_msk) \ >>> + do { \ >>> + if ((cfg_in) & (opt_msk)) { \ >>> + (state)->vid_config &= ~(opt_msk); \ >>> + (state)->vid_config |= (cfg_in) & (opt_msk); \ >>> + } \ >>> + } while (0) >>> + >>> +#define CX25840_VCONFIG_SET_BIT(state, opt_msk, voc, idx, bit, oneval) \ >>> + do { \ >>> + if ((state)->vid_config & (opt_msk)) { \ >>> + if (((state)->vid_config & (opt_msk)) == \ >>> + (oneval)) \ >>> + (voc)[idx] |= BIT(bit); \ >>> + else \ >>> + (voc)[idx] &= ~BIT(bit); \ >>> + } \ >>> + } while (0) >>> + >>> +int cx25840_vconfig(struct i2c_client *client, u32 cfg_in) >>> +{ >>> + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); >>> + u8 voutctrl[3]; >>> + unsigned int i; >>> + >>> + /* apply incoming options to the current state */ >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_FMT_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_RES_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VBIRAW_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ANCDATA_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_TASKBIT_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ACTIVE_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VALID_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_HRESETW_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_CLKGATE_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_DCMODE_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_IDID0S_MASK); >>> + CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VIPCLAMP_MASK); >> >> This appears to be a very complex way of saying: >> >> state->vid_config = cfg_in; > > This is supposed to change in vid_config only these options that are set > in the incoming cfg_in, leaving the rest as-is. > > If the code simply assigns cfg_in to vid_config it will also clear all the > existing options. Ah yes, but see my reply below at the end. > >> >>> + >>> + for (i = 0; i < 3; i++) >>> + voutctrl[i] = cx25840_read(client, 0x404 + i); >>> + >>> + /* apply state to hardware regs */ >>> + if (state->vid_config & CX25840_VCONFIG_FMT_MASK) >>> + voutctrl[0] &= ~3; >>> + switch (state->vid_config & CX25840_VCONFIG_FMT_MASK) { >>> + case CX25840_VCONFIG_FMT_BT656: >>> + voutctrl[0] |= 1; >>> + break; >>> + >>> + case CX25840_VCONFIG_FMT_VIP11: >>> + voutctrl[0] |= 2; >>> + break; >>> + >>> + case CX25840_VCONFIG_FMT_VIP2: >>> + voutctrl[0] |= 3; >>> + break; >>> + >>> + case CX25840_VCONFIG_FMT_BT601: >>> + /* zero */ >>> + default: >>> + break; >>> + } >>> + >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_RES_MASK, voutctrl, >>> + 0, 2, CX25840_VCONFIG_RES_10BIT); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VBIRAW_MASK, voutctrl, >>> + 0, 3, CX25840_VCONFIG_VBIRAW_ENABLED); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ANCDATA_MASK, voutctrl, >>> + 0, 4, CX25840_VCONFIG_ANCDATA_ENABLED); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_TASKBIT_MASK, voutctrl, >>> + 0, 5, CX25840_VCONFIG_TASKBIT_ONE); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ACTIVE_MASK, voutctrl, >>> + 1, 2, CX25840_VCONFIG_ACTIVE_HORIZONTAL); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VALID_MASK, voutctrl, >>> + 1, 3, CX25840_VCONFIG_VALID_ANDACTIVE); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_HRESETW_MASK, voutctrl, >>> + 1, 4, CX25840_VCONFIG_HRESETW_PIXCLK); >>> + >>> + if (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) >>> + voutctrl[1] &= ~(3 << 6); >>> + switch (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) { >>> + case CX25840_VCONFIG_CLKGATE_VALID: >>> + voutctrl[1] |= 2; >>> + break; >>> + >>> + case CX25840_VCONFIG_CLKGATE_VALIDACTIVE: >>> + voutctrl[1] |= 3; >>> + break; >>> + >>> + case CX25840_VCONFIG_CLKGATE_NONE: >>> + /* zero */ >>> + default: >>> + break; >>> + } >>> + >>> + >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_DCMODE_MASK, voutctrl, >>> + 2, 0, CX25840_VCONFIG_DCMODE_BYTES); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_IDID0S_MASK, voutctrl, >>> + 2, 1, CX25840_VCONFIG_IDID0S_LINECNT); >>> + CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VIPCLAMP_MASK, voutctrl, >>> + 2, 4, CX25840_VCONFIG_VIPCLAMP_ENABLED); >>> + >>> + for (i = 0; i < 3; i++) >>> + cx25840_write(client, 0x404 + i, voutctrl[i]); >>> + >>> + return 0; >>> +} >>> + >>> +#undef CX25840_VCONFIG_SET_BIT >>> +#undef CX25840_VCONFIG_OPTION >> >> Why #undef? You would normally never do that. > > The idea here is to catch (unintended) other users of these macros, other > than cx25840_vconfig() and to not pollute the macro namespace. > But these #undefs can be removed if they are against the coding style. Please remove. You do not normally use #undef unless you are redefining a macro. > >> >>> + >>> /* ----------------------------------------------------------------------- */ >>> >>> /* This load_fw operation must be called to load the driver's firmware. >>> @@ -1836,6 +2226,9 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd, >>> if (is_cx23888(state)) >>> cx23888_std_setup(client); >>> >>> + if (is_cx2584x(state) && state->generic_mode) >>> + cx25840_vconfig(client, config); >>> + >> >> You do the vconfig configuration when the video routing changes. But isn't this >> configuration a one-time thing? E.g. something you do only when initializing the >> board? >> >> At least in the cxusb code the cfg_in value is constant and not dependent on what >> input is chosen. >> >> If this is true, then you should add the core init op instead. And as a bonus you >> can turn on generic_mode if the init op is called instead of having to add it >> to the platform data. >> > > The problem here is that the Medion MD95700 has two modes: > digital (DVB-T) and analog. > When it is operating in the digital mode the device analog components > (including the cx25840 chip) have their power cut by the hardware. > > This means that the cx25840 has to be fully reinitialized (firmware > loaded, format set, etc.) every time the user opens the Medion's v4l2 > video or radio device node if the device has previously operated in the > DVB-T mode. > Mode switching is supported transparently by the driver without needing > to reload the module or reconnect the device. So? You call the core init op to initialize vconfig (just pass in all the bits to simplify things), and whenever s_video_routing it called the driver will just call cx25840_vconfig() with the vconfig value set by the core init op. As far as I can see all you want to do is to specify a specific vconfig value that should be applied whenever s_video_routing is called. So in cxusb_medion_analog_init() you call the core init op, then the video s_routing op to switch to COMPOSITE1. I like that much better since vconfig doesn't change when you switch inputs. It's only needed when you initialize the analog part. Regards, Hans > >> >> Regards, >> >> Hans >> > > Thanks and best regards, > Maciej >