From patchwork Mon Feb 29 13:12:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshihiro Kaneko X-Patchwork-Id: 8453801 X-Patchwork-Delegate: horms@verge.net.au Return-Path: X-Original-To: patchwork-linux-renesas-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0C4289F372 for ; Mon, 29 Feb 2016 13:14:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1C2EA20166 for ; Mon, 29 Feb 2016 13:14:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 17A882013D for ; Mon, 29 Feb 2016 13:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752948AbcB2NOA (ORCPT ); Mon, 29 Feb 2016 08:14:00 -0500 Received: from mail-pf0-f173.google.com ([209.85.192.173]:34117 "EHLO mail-pf0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751547AbcB2NN7 (ORCPT ); Mon, 29 Feb 2016 08:13:59 -0500 Received: by mail-pf0-f173.google.com with SMTP id 4so14107785pfd.1; Mon, 29 Feb 2016 05:13:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tkCOU3+KtukPr4IUhghFZ1Ae5K+5tvh5d1O9e6dulSE=; b=Xt/XCU9IDpdFxx5WdwmXGPVFbShvTG9geQWewKFDruibwRPVUyp8qOtd0m5DxAdGQA i2HD341ulE1rplqNNHLWnLSvOjsE3zG1nhCA4g2g08MeHrgqGYzi8VeiZhdLO7P7BL0g DOFdOOOPirCObSQ52WZABUjc4wQ9oCwDai6gMuM5mGVsJ73bIxxaXhp6dmPFahmz1mZY EZa+f+PojwEFbh4y8MhPM6eNxJnOOIpYc5QE2qqJnSvEEcESo/x1EQ3lb8lET3H7tffP +qAZ8ZXiZgnoY2hmJ+yWl/oZvun42Aoo2VS0Pwux1N6sPhtHLxBeOw3Bf9tcUkSwS7hJ VBnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tkCOU3+KtukPr4IUhghFZ1Ae5K+5tvh5d1O9e6dulSE=; b=mc7TH+mdT09JefryGXEF2e+/WFP1vETN1LrGVlcjQHPj+qod5PKAV7wL8o10tJxyHk vMgaO9H7Bv5/MXQzHF2DKvsheo6bqRzoy6vdyIIwUOjXlVQ9pC07rvSewJV8Sw7AKLpo HIbv74Yzx2Jk36r5EN/0CUOhJrrs1utZbADnSAxC20AVmRxF3+jfC6N2s4bIcMldudwI fb9nA4Q4FCu+FsM4EtzrpVe2lgAHOs2dSENkfyNNYXtzsr+KyUIMsudlJmACpk0o/3XK dqVKzoN4zRbFYckEtWdxjTpoRC0otH8UewmOJZyEK67m77Yu4bXkXkOsuQXlXslylCeh 4XMA== X-Gm-Message-State: AD7BkJK5+EIQIJFCm9mY2I+k+11RzZNVfHaweGgAuq9hpt8CJWKkLod9Jt/MMLqSl2jLSA== X-Received: by 10.98.42.8 with SMTP id q8mr22262606pfq.13.1456751638482; Mon, 29 Feb 2016 05:13:58 -0800 (PST) Received: from macc.flets-east.jp (p3469131-ipngn19901marunouchi.tokyo.ocn.ne.jp. [153.229.6.131]) by smtp.gmail.com with ESMTPSA id c9sm38150913pfd.90.2016.02.29.05.13.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 29 Feb 2016 05:13:57 -0800 (PST) From: Yoshihiro Kaneko To: linux-media@vger.kernel.org Cc: Guennadi Liakhovetski , Simon Horman , Magnus Damm , linux-renesas-soc@vger.kernel.org Subject: [PATCH/RFC 1/4] media: soc_camera: rcar_vin: Add UDS support Date: Mon, 29 Feb 2016 22:12:40 +0900 Message-Id: <1456751563-21246-2-git-send-email-ykaneko0929@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1456751563-21246-1-git-send-email-ykaneko0929@gmail.com> References: <1456751563-21246-1-git-send-email-ykaneko0929@gmail.com> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Spam-Status: No, score=-7.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Yoshihiko Mori Add UDS control for R-Car Gen3. Up down scaler can be vertical and horizontal scaling. Signed-off-by: Yoshihiko Mori Signed-off-by: Koji Matsuoka Signed-off-by: Yoshihiro Kaneko --- drivers/media/platform/soc_camera/rcar_vin.c | 175 +++++++++++++++++++++------ 1 file changed, 140 insertions(+), 35 deletions(-) diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index dc75a80..a22141b 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -90,6 +90,7 @@ /* Register bit fields for R-Car VIN */ /* Video n Main Control Register bits */ +#define VNMC_SCLE (1 << 26) #define VNMC_FOC (1 << 21) #define VNMC_YCAL (1 << 19) #define VNMC_INF_YUV8_BT656 (0 << 16) @@ -132,6 +133,17 @@ #define VNDMR2_FTEV (1 << 17) #define VNDMR2_VLV(n) ((n & 0xf) << 12) +/* UDS */ +#define VNUDS_CTRL_REG 0x80 /* Scaling Control Registers */ +#define VNUDS_CTRL_AMD (1 << 30) +#define VNUDS_CTRL_BC (1 << 20) +#define VNUDS_CTRL_TDIPC (1 << 1) + +#define VNUDS_SCALE_REG 0x84 /* Scaling Factor Register */ +#define VNUDS_PASS_BWIDTH_REG 0x90 /* Passband Registers */ +#define VNUDS_IPC_REG 0x98 /* 2D IPC Setting Register */ +#define VNUDS_CLIP_SIZE_REG 0xA4 /* UDS Output Size Clipping Register */ + #define VIN_MAX_WIDTH 2048 #define VIN_MAX_HEIGHT 2048 @@ -526,6 +538,14 @@ struct rcar_vin_cam { const struct soc_mbus_pixelfmt *extra_fmt; }; +static inline int is_scaling(struct rcar_vin_cam *cam) +{ + if (cam->width != cam->out_width || cam->height != cam->out_height) + return 1; + + return 0; +} + /* * .queue_setup() is called to check whether the driver can accept the requested * number of buffers and to fill in plane sizes for the current frame format if @@ -667,6 +687,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) if (input_is_yuv == output_is_yuv) vnmc |= VNMC_BPS; + if (priv->chip == RCAR_GEN3 && is_scaling(cam)) + vnmc |= VNMC_SCLE; + /* progressive or interlaced mode */ interrupts = progressive ? VNIE_FIE : VNIE_EFE; @@ -973,6 +996,75 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) icd->devnum); } +struct rcar_vin_uds_regs { + unsigned long ctrl; + unsigned long scale; + unsigned long pass_bwidth; + unsigned long clip_size; +}; + +static unsigned long rcar_vin_get_bwidth(unsigned long ratio) +{ + unsigned long bwidth; + unsigned long mant, frac; + + mant = (ratio & 0xF000) >> 12; + frac = ratio & 0x0FFF; + if (mant) + bwidth = 64 * 4096 * mant / (4096 * mant + frac); + else + bwidth = 64; + + return bwidth; +} + +static unsigned long rcar_vin_compute_ratio(unsigned int input, + unsigned int output) +{ +#ifdef DISABLE_UDS_CTRL_AMD + return (input - 1) * 4096 / (output - 1); +#else + if (output > input) + return input * 4096 / output; + else + return (input - 1) * 4096 / (output - 1); +#endif +} + +int rcar_vin_uds_set(struct rcar_vin_priv *priv, struct rcar_vin_cam *cam) +{ + struct rcar_vin_uds_regs regs; + unsigned long ratio_h, ratio_v; + unsigned long bwidth_h, bwidth_v; + unsigned long ctrl; + unsigned long clip_size; + struct v4l2_rect *cam_subrect = &cam->subrect; + u32 vnmc; + + ratio_h = rcar_vin_compute_ratio(cam_subrect->width, cam->out_width); + ratio_v = rcar_vin_compute_ratio(cam_subrect->height, cam->out_height); + + bwidth_h = rcar_vin_get_bwidth(ratio_h); + bwidth_v = rcar_vin_get_bwidth(ratio_v); + + ctrl = VNUDS_CTRL_AMD; + clip_size = (cam->out_width << 16) | cam->out_height; + + regs.ctrl = ctrl; + regs.scale = (ratio_h << 16) | ratio_v; + regs.pass_bwidth = (bwidth_h << 16) | bwidth_v; + regs.clip_size = clip_size; + + vnmc = ioread32(priv->base + VNMC_REG); + iowrite32(vnmc | VNMC_SCLE, priv->base + VNMC_REG); + iowrite32(regs.ctrl, priv->base + VNUDS_CTRL_REG); + iowrite32(regs.scale, priv->base + VNUDS_SCALE_REG); + iowrite32(regs.pass_bwidth, priv->base + VNUDS_PASS_BWIDTH_REG); + iowrite32(regs.clip_size, priv->base + VNUDS_CLIP_SIZE_REG); + + return 0; +} + static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs) { int i; @@ -1037,6 +1129,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) unsigned char dsize = 0; struct v4l2_rect *cam_subrect = &cam->subrect; u32 value; + int ret; dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", icd->user_width, icd->user_height, cam->vin_left, cam->vin_top); @@ -1073,48 +1166,60 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) break; } - /* Set scaling coefficient */ - value = 0; - if (cam_subrect->height != cam->out_height) - value = (4096 * cam_subrect->height) / cam->out_height; - dev_dbg(icd->parent, "YS Value: %x\n", value); - iowrite32(value, priv->base + VNYS_REG); - - value = 0; - if (cam_subrect->width != cam->out_width) - value = (4096 * cam_subrect->width) / cam->out_width; + if (priv->chip == RCAR_GEN3 && is_scaling(cam) { + ret = rcar_vin_uds_set(priv, cam); + if (ret < 0) + return ret; + iowrite32(ALIGN(cam->out_width, 0x20), priv->base + VNIS_REG); + } else { + /* Set scaling coefficient */ + value = 0; + if (cam_subrect->height != cam->out_height) + value = (4096 * cam_subrect->height) / cam->out_height; + dev_dbg(icd->parent, "YS Value: %x\n", value); + iowrite32(value, priv->base + VNYS_REG); - /* Horizontal upscaling is up to double size */ - if (0 < value && value < 2048) - value = 2048; + value = 0; + if (cam_subrect->width != cam->out_width) + value = (4096 * cam_subrect->width) / cam->out_width; - dev_dbg(icd->parent, "XS Value: %x\n", value); - iowrite32(value, priv->base + VNXS_REG); + /* Horizontal upscaling is up to double size */ + if (value > 0 && value < 2048) + value = 2048; - /* Horizontal upscaling is carried out by scaling down from double size */ - if (value < 4096) - value *= 2; + dev_dbg(icd->parent, "XS Value: %x\n", value); + iowrite32(value, priv->base + VNXS_REG); - set_coeff(priv, value); + /* + * Horizontal upscaling is carried out + * by scaling down from double size + */ + if (value < 4096) + value *= 2; + + set_coeff(priv, value); + + /* Set Start/End Pixel/Line Post-Clip */ + iowrite32(0, priv->base + VNSPPOC_REG); + iowrite32(0, priv->base + VNSLPOC_REG); + iowrite32((cam->out_width - 1) << dsize, + priv->base + VNEPPOC_REG); + switch (priv->field) { + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_INTERLACED_BT: + iowrite32(cam->out_height / 2 - 1, + priv->base + VNELPOC_REG); + break; + default: + iowrite32(cam->out_height - 1, + priv->base + VNELPOC_REG); + break; + } - /* Set Start/End Pixel/Line Post-Clip */ - iowrite32(0, priv->base + VNSPPOC_REG); - iowrite32(0, priv->base + VNSLPOC_REG); - iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG); - switch (priv->field) { - case V4L2_FIELD_INTERLACED: - case V4L2_FIELD_INTERLACED_TB: - case V4L2_FIELD_INTERLACED_BT: - iowrite32(cam->out_height / 2 - 1, - priv->base + VNELPOC_REG); - break; - default: - iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG); - break; + iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG); } - iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG); - return 0; }