linux_dsm_epyc7002/drivers/gpu/drm/meson/meson_venc.c

1701 lines
46 KiB
C
Raw Normal View History

drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
/*
* Copyright (C) 2016 BayLibre, SAS
* Author: Neil Armstrong <narmstrong@baylibre.com>
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <drm/drmP.h>
#include "meson_drv.h"
#include "meson_venc.h"
#include "meson_vpp.h"
#include "meson_vclk.h"
#include "meson_registers.h"
/**
* DOC: Video Encoder
*
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
* VENC Handle the pixels encoding to the output formats.
* We handle the following encodings :
*
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
* - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
* - TMDS/HDMI Encoding via ENCI_DIV and ENCP
* - Setup of more clock rates for HDMI modes
*
* What is missing :
*
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
* - LCD Panel encoding via ENCL
* - TV Panel encoding via ENCT
*
* VENC paths :
*
* .. code::
*
* _____ _____ ____________________
* vd1---| |-| | | VENC /---------|----VDAC
* vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-|
* osd1--| |-| | | \ | X--HDMI-TX
* osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|-|
* | | |
* | \--ENCL-----------|----LVDS
* |____________________|
*
* The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
* directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
* The ENCP is designed for Progressive encoding but can also generate
* 1080i interlaced pixels, and was initialy desined to encode pixels for
* VDAC to output RGB ou YUV analog outputs.
* It's output is only used through the ENCP_DVI encoder for HDMI.
* The ENCL LVDS encoder is not implemented.
*
* The ENCI and ENCP encoders needs specially defined parameters for each
* supported mode and thus cannot be determined from standard video timings.
*
* The ENCI end ENCP DVI encoders are more generic and can generate any timings
* from the pixel data generated by ENCI or ENCP, so can use the standard video
* timings are source for HW parameters.
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
*/
/* HHI Registers */
drm/meson: Fixes for drm_crtc_vblank_on/off support Since Linux 4.17, calls to drm_crtc_vblank_on/off are mandatory, and we get a warning when ctrc is disabled : " driver forgot to call drm_crtc_vblank_off()" But, the vsync IRQ was not totally disabled due the transient hardware state and specific interrupt line, thus adding proper IRQ masking from the HHI system control registers. The last change fixes a race condition introduced by calling the added drm_crtc_vblank_on/off when an HPD event occurs from the HDMI connector, triggering a WARN_ON() in the _atomic_begin() callback when the CRTC is disabled, thus also triggering a WARN_ON() in drm_vblank_put() : WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/meson/meson_crtc.c:157 meson_crtc_atomic_begin+0x78/0x80 [...] Call trace: meson_crtc_atomic_begin+0x78/0x80 drm_atomic_helper_commit_planes+0x140/0x218 drm_atomic_helper_commit_tail+0x38/0x80 commit_tail+0x7c/0x80 drm_atomic_helper_commit+0xdc/0x150 drm_atomic_commit+0x54/0x60 restore_fbdev_mode_atomic+0x198/0x238 restore_fbdev_mode+0x6c/0x1c0 drm_fb_helper_restore_fbdev_mode_unlocked+0x7c/0xf0 drm_fb_helper_set_par+0x34/0x60 drm_fb_helper_hotplug_event.part.28+0xb8/0xc8 drm_fbdev_client_hotplug+0xa4/0xe0 drm_client_dev_hotplug+0x90/0xe0 drm_kms_helper_hotplug_event+0x3c/0x48 drm_helper_hpd_irq_event+0x134/0x168 dw_hdmi_top_thread_irq+0x3c/0x50 [...] WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/drm_vblank.c:1026 drm_vblank_put+0xb4/0xc8 [...] Call trace: drm_vblank_put+0xb4/0xc8 drm_crtc_vblank_put+0x24/0x30 drm_atomic_helper_wait_for_vblanks.part.9+0x130/0x2b8 drm_atomic_helper_commit_tail+0x68/0x80 [...] The issue is that vblank need to be enabled in any occurrence of : - atomic_enable() - atomic_begin() and state->enable == true, which was not the case Moving the CRTC enable code to a common function and calling in one of these occurrence solves this race condition and makes sure vblank is enabled in each call to _atomic_begin() from the HPD event leading to drm_atomic_helper_commit_planes(). To Summarize : - Make sure that the CRTC code will call the drm_crtc_vblank_on()/off() - *Really* mask the Vsync IRQ - Initialize and enable vblank at the first atomic_begin()/_atomic_enable() Cc: stable@vger.kernel.org # 4.17+ Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Lyude Paul <lyude@redhat.com> [fixed typos+added cc for stable] Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181122160103.10993-1-narmstrong@baylibre.com Signed-off-by: Sean Paul <seanpaul@chromium.org>
2018-11-22 23:01:03 +07:00
#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
.mode_tag = MESON_VENC_MODE_CVBS_PAL,
.hso_begin = 3,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 7,
.video_prog_mode = 0xff,
.video_mode = 0x13,
.sch_adjust = 0x28,
.yc_delay = 0x343,
.pixel_start = 251,
.pixel_end = 1691,
.top_field_line_start = 22,
.top_field_line_end = 310,
.bottom_field_line_start = 23,
.bottom_field_line_end = 311,
.video_saturation = 9,
.video_contrast = 0,
.video_brightness = 0,
.video_hue = 0,
.analog_sync_adj = 0x8080,
};
struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
.mode_tag = MESON_VENC_MODE_CVBS_NTSC,
.hso_begin = 5,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 0xb,
.video_prog_mode = 0xf0,
.video_mode = 0x8,
.sch_adjust = 0x20,
.yc_delay = 0x333,
.pixel_start = 227,
.pixel_end = 1667,
.top_field_line_start = 18,
.top_field_line_end = 258,
.bottom_field_line_start = 19,
.bottom_field_line_end = 259,
.video_saturation = 18,
.video_contrast = 3,
.video_brightness = 0,
.video_hue = 0,
.analog_sync_adj = 0x9c00,
};
union meson_hdmi_venc_mode {
struct {
unsigned int mode_tag;
unsigned int hso_begin;
unsigned int hso_end;
unsigned int vso_even;
unsigned int vso_odd;
unsigned int macv_max_amp;
unsigned int video_prog_mode;
unsigned int video_mode;
unsigned int sch_adjust;
unsigned int yc_delay;
unsigned int pixel_start;
unsigned int pixel_end;
unsigned int top_field_line_start;
unsigned int top_field_line_end;
unsigned int bottom_field_line_start;
unsigned int bottom_field_line_end;
} enci;
struct {
unsigned int dvi_settings;
unsigned int video_mode;
unsigned int video_mode_adv;
unsigned int video_prog_mode;
bool video_prog_mode_present;
unsigned int video_sync_mode;
bool video_sync_mode_present;
unsigned int video_yc_dly;
bool video_yc_dly_present;
unsigned int video_rgb_ctrl;
bool video_rgb_ctrl_present;
unsigned int video_filt_ctrl;
bool video_filt_ctrl_present;
unsigned int video_ofld_voav_ofst;
bool video_ofld_voav_ofst_present;
unsigned int yfp1_htime;
unsigned int yfp2_htime;
unsigned int max_pxcnt;
unsigned int hspuls_begin;
unsigned int hspuls_end;
unsigned int hspuls_switch;
unsigned int vspuls_begin;
unsigned int vspuls_end;
unsigned int vspuls_bline;
unsigned int vspuls_eline;
unsigned int eqpuls_begin;
bool eqpuls_begin_present;
unsigned int eqpuls_end;
bool eqpuls_end_present;
unsigned int eqpuls_bline;
bool eqpuls_bline_present;
unsigned int eqpuls_eline;
bool eqpuls_eline_present;
unsigned int havon_begin;
unsigned int havon_end;
unsigned int vavon_bline;
unsigned int vavon_eline;
unsigned int hso_begin;
unsigned int hso_end;
unsigned int vso_begin;
unsigned int vso_end;
unsigned int vso_bline;
unsigned int vso_eline;
bool vso_eline_present;
unsigned int sy_val;
bool sy_val_present;
unsigned int sy2_val;
bool sy2_val_present;
unsigned int max_lncnt;
} encp;
};
union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
.enci = {
.hso_begin = 5,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 0x810b,
.video_prog_mode = 0xf0,
.video_mode = 0x8,
.sch_adjust = 0x20,
.yc_delay = 0,
.pixel_start = 227,
.pixel_end = 1667,
.top_field_line_start = 18,
.top_field_line_end = 258,
.bottom_field_line_start = 19,
.bottom_field_line_end = 259,
},
};
union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
.enci = {
.hso_begin = 3,
.hso_end = 129,
.vso_even = 3,
.vso_odd = 260,
.macv_max_amp = 8107,
.video_prog_mode = 0xff,
.video_mode = 0x13,
.sch_adjust = 0x28,
.yc_delay = 0x333,
.pixel_start = 251,
.pixel_end = 1691,
.top_field_line_start = 22,
.top_field_line_end = 310,
.bottom_field_line_start = 23,
.bottom_field_line_end = 311,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
.video_mode_adv = 0x9,
.video_prog_mode = 0,
.video_prog_mode_present = true,
.video_sync_mode = 7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x2052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 244,
.yfp2_htime = 1630,
.max_pxcnt = 1715,
.hspuls_begin = 0x22,
.hspuls_end = 0xa0,
.hspuls_switch = 88,
.vspuls_begin = 0,
.vspuls_end = 1589,
.vspuls_bline = 0,
.vspuls_eline = 5,
.havon_begin = 249,
.havon_end = 1689,
.vavon_bline = 42,
.vavon_eline = 521,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 3,
.hso_end = 5,
.vso_begin = 3,
.vso_end = 5,
.vso_bline = 0,
/* vso_eline */
.sy_val = 8,
.sy_val_present = true,
.sy2_val = 0x1d8,
.sy2_val_present = true,
.max_lncnt = 524,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
.encp = {
.dvi_settings = 0x21,
.video_mode = 0x4000,
.video_mode_adv = 0x9,
.video_prog_mode = 0,
.video_prog_mode_present = true,
.video_sync_mode = 7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x52,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 235,
.yfp2_htime = 1674,
.max_pxcnt = 1727,
.hspuls_begin = 0,
.hspuls_end = 0x80,
.hspuls_switch = 88,
.vspuls_begin = 0,
.vspuls_end = 1599,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 235,
.havon_end = 1674,
.vavon_bline = 44,
.vavon_eline = 619,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 0x80,
.hso_end = 0,
.vso_begin = 0,
.vso_end = 5,
.vso_bline = 0,
/* vso_eline */
.sy_val = 8,
.sy_val_present = true,
.sy2_val = 0x1d8,
.sy2_val_present = true,
.max_lncnt = 624,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x4040,
.video_mode_adv = 0x19,
/* video_prog_mode */
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 648,
.yfp2_htime = 3207,
.max_pxcnt = 3299,
.hspuls_begin = 80,
.hspuls_end = 240,
.hspuls_switch = 80,
.vspuls_begin = 688,
.vspuls_end = 3248,
.vspuls_bline = 4,
.vspuls_eline = 8,
.havon_begin = 648,
.havon_end = 3207,
.vavon_bline = 29,
.vavon_eline = 748,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 256,
.hso_end = 168,
.vso_begin = 168,
.vso_end = 256,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 749,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x4040,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x407,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
/* video_rgb_ctrl */
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 648,
.yfp2_htime = 3207,
.max_pxcnt = 3959,
.hspuls_begin = 80,
.hspuls_end = 240,
.hspuls_switch = 80,
.vspuls_begin = 688,
.vspuls_end = 3248,
.vspuls_bline = 4,
.vspuls_eline = 8,
.havon_begin = 648,
.havon_end = 3207,
.vavon_bline = 29,
.vavon_eline = 748,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 128,
.hso_end = 208,
.vso_begin = 128,
.vso_end = 128,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 749,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
.encp = {
.dvi_settings = 0x2029,
.video_mode = 0x5ffc,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x207,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
.video_ofld_voav_ofst = 0x11,
.video_ofld_voav_ofst_present = true,
.yfp1_htime = 516,
.yfp2_htime = 4355,
.max_pxcnt = 4399,
.hspuls_begin = 88,
.hspuls_end = 264,
.hspuls_switch = 88,
.vspuls_begin = 440,
.vspuls_end = 2200,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 516,
.havon_end = 4355,
.vavon_bline = 20,
.vavon_eline = 559,
.eqpuls_begin = 2288,
.eqpuls_begin_present = true,
.eqpuls_end = 2464,
.eqpuls_end_present = true,
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 264,
.hso_end = 176,
.vso_begin = 88,
.vso_end = 88,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
.encp = {
.dvi_settings = 0x202d,
.video_mode = 0x5ffc,
.video_mode_adv = 0x19,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
/* video_yc_dly */
/* video_rgb_ctrl */
/* video_filt_ctrl */
.video_ofld_voav_ofst = 0x11,
.video_ofld_voav_ofst_present = true,
.yfp1_htime = 526,
.yfp2_htime = 4365,
.max_pxcnt = 5279,
.hspuls_begin = 88,
.hspuls_end = 264,
.hspuls_switch = 88,
.vspuls_begin = 440,
.vspuls_end = 2200,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 526,
.havon_end = 4365,
.vavon_bline = 20,
.vavon_eline = 559,
.eqpuls_begin = 2288,
.eqpuls_begin_present = true,
.eqpuls_end = 2464,
.eqpuls_end_present = true,
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 142,
.hso_end = 230,
.vso_begin = 142,
.vso_end = 142,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
.video_rgb_ctrl = 2,
.video_rgb_ctrl_present = true,
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 271,
.yfp2_htime = 2190,
.max_pxcnt = 2749,
.hspuls_begin = 44,
.hspuls_end = 132,
.hspuls_switch = 44,
.vspuls_begin = 220,
.vspuls_end = 2140,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 271,
.havon_end = 2190,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 79,
.hso_end = 123,
.vso_begin = 79,
.vso_end = 79,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 2060,
.max_pxcnt = 2199,
.hspuls_begin = 2156,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 2067,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156,
.vso_begin = 2100,
.vso_end = 2164,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
.encp = {
.dvi_settings = 0xd,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
.video_sync_mode = 0x7,
.video_sync_mode_present = true,
.video_yc_dly = 0,
.video_yc_dly_present = true,
.video_rgb_ctrl = 2,
.video_rgb_ctrl_present = true,
/* video_filt_ctrl */
/* video_ofld_voav_ofst */
.yfp1_htime = 271,
.yfp2_htime = 2190,
.max_pxcnt = 2639,
.hspuls_begin = 44,
.hspuls_end = 132,
.hspuls_switch = 44,
.vspuls_begin = 220,
.vspuls_end = 2140,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 271,
.havon_end = 2190,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
.eqpuls_bline = 0,
.eqpuls_bline_present = true,
.eqpuls_eline = 4,
.eqpuls_eline_present = true,
.hso_begin = 79,
.hso_end = 123,
.vso_begin = 79,
.vso_end = 79,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x18,
.video_prog_mode = 0x100,
.video_prog_mode_present = true,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1052,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 2060,
.max_pxcnt = 2199,
.hspuls_begin = 2156,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 2067,
.vavon_bline = 41,
.vavon_eline = 1120,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156,
.vso_begin = 2100,
.vso_end = 2164,
.vso_bline = 0,
.vso_eline = 5,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 1124,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x8,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1000,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 140+3840,
.max_pxcnt = 3840+1660-1,
.hspuls_begin = 2156+1920,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059+1920,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 3987,
.vavon_bline = 89,
.vavon_eline = 2248,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156+1920,
.vso_begin = 2100+1920,
.vso_end = 2164+1920,
.vso_bline = 51,
.vso_eline = 53,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 2249,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x8,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1000,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 140+3840,
.max_pxcnt = 3840+1440-1,
.hspuls_begin = 2156+1920,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059+1920,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 3987,
.vavon_bline = 89,
.vavon_eline = 2248,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156+1920,
.vso_begin = 2100+1920,
.vso_end = 2164+1920,
.vso_bline = 51,
.vso_eline = 53,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 2249,
},
};
union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
.encp = {
.dvi_settings = 0x1,
.video_mode = 0x4040,
.video_mode_adv = 0x8,
/* video_sync_mode */
/* video_yc_dly */
/* video_rgb_ctrl */
.video_filt_ctrl = 0x1000,
.video_filt_ctrl_present = true,
/* video_ofld_voav_ofst */
.yfp1_htime = 140,
.yfp2_htime = 140+3840,
.max_pxcnt = 3840+560-1,
.hspuls_begin = 2156+1920,
.hspuls_end = 44,
.hspuls_switch = 44,
.vspuls_begin = 140,
.vspuls_end = 2059+1920,
.vspuls_bline = 0,
.vspuls_eline = 4,
.havon_begin = 148,
.havon_end = 3987,
.vavon_bline = 89,
.vavon_eline = 2248,
/* eqpuls_begin */
/* eqpuls_end */
/* eqpuls_bline */
/* eqpuls_eline */
.hso_begin = 44,
.hso_end = 2156+1920,
.vso_begin = 2100+1920,
.vso_end = 2164+1920,
.vso_bline = 51,
.vso_eline = 53,
.vso_eline_present = true,
/* sy_val */
/* sy2_val */
.max_lncnt = 2249,
},
};
struct meson_hdmi_venc_vic_mode {
unsigned int vic;
union meson_hdmi_venc_mode *mode;
} meson_hdmi_venc_vic_modes[] = {
{ 6, &meson_hdmi_enci_mode_480i },
{ 7, &meson_hdmi_enci_mode_480i },
{ 21, &meson_hdmi_enci_mode_576i },
{ 22, &meson_hdmi_enci_mode_576i },
{ 2, &meson_hdmi_encp_mode_480p },
{ 3, &meson_hdmi_encp_mode_480p },
{ 17, &meson_hdmi_encp_mode_576p },
{ 18, &meson_hdmi_encp_mode_576p },
{ 4, &meson_hdmi_encp_mode_720p60 },
{ 19, &meson_hdmi_encp_mode_720p50 },
{ 5, &meson_hdmi_encp_mode_1080i60 },
{ 20, &meson_hdmi_encp_mode_1080i50 },
{ 32, &meson_hdmi_encp_mode_1080p24 },
{ 33, &meson_hdmi_encp_mode_1080p50 },
{ 34, &meson_hdmi_encp_mode_1080p30 },
{ 31, &meson_hdmi_encp_mode_1080p50 },
{ 16, &meson_hdmi_encp_mode_1080p60 },
{ 93, &meson_hdmi_encp_mode_2160p24 },
{ 94, &meson_hdmi_encp_mode_2160p25 },
{ 95, &meson_hdmi_encp_mode_2160p30 },
{ 96, &meson_hdmi_encp_mode_2160p25 },
{ 97, &meson_hdmi_encp_mode_2160p30 },
{ 0, NULL}, /* sentinel */
};
static signed int to_signed(unsigned int a)
{
if (a <= 7)
return a;
else
return a - 16;
}
static unsigned long modulo(unsigned long a, unsigned long b)
{
if (a >= b)
return a - b;
else
return a;
}
enum drm_mode_status
meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
{
if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
return MODE_BAD;
if (mode->hdisplay < 640 || mode->hdisplay > 1920)
return MODE_BAD_HVALUE;
if (mode->vdisplay < 480 || mode->vdisplay > 1200)
return MODE_BAD_VVALUE;
return MODE_OK;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
bool meson_venc_hdmi_supported_vic(int vic)
{
struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
while (vmode->vic && vmode->mode) {
if (vmode->vic == vic)
return true;
vmode++;
}
return false;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
union meson_hdmi_venc_mode *dmt_mode)
{
memset(dmt_mode, 0, sizeof(*dmt_mode));
dmt_mode->encp.dvi_settings = 0x21;
dmt_mode->encp.video_mode = 0x4040;
dmt_mode->encp.video_mode_adv = 0x18;
dmt_mode->encp.max_pxcnt = mode->htotal - 1;
dmt_mode->encp.havon_begin = mode->htotal - mode->hsync_start;
dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
mode->hdisplay - 1;
dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start;
dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
mode->vdisplay - 1;
dmt_mode->encp.hso_begin = 0;
dmt_mode->encp.hso_end = mode->hsync_end - mode->hsync_start;
dmt_mode->encp.vso_begin = 30;
dmt_mode->encp.vso_end = 50;
dmt_mode->encp.vso_bline = 0;
dmt_mode->encp.vso_eline = mode->vsync_end - mode->vsync_start;
dmt_mode->encp.vso_eline_present = true;
dmt_mode->encp.max_lncnt = mode->vtotal - 1;
}
static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
{
struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
while (vmode->vic && vmode->mode) {
if (vmode->vic == vic)
return vmode->mode;
vmode++;
}
return NULL;
}
bool meson_venc_hdmi_venc_repeat(int vic)
{
/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
if (vic == 6 || vic == 7 || /* 480i */
vic == 21 || vic == 22 || /* 576i */
vic == 17 || vic == 18 || /* 576p */
vic == 2 || vic == 3 || /* 480p */
vic == 4 || /* 720p60 */
vic == 19 || /* 720p50 */
vic == 5 || /* 1080i60 */
vic == 20) /* 1080i50 */
return true;
return false;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
struct drm_display_mode *mode)
{
union meson_hdmi_venc_mode *vmode = NULL;
union meson_hdmi_venc_mode vmode_dmt;
bool use_enci = false;
bool venc_repeat = false;
bool hdmi_repeat = false;
unsigned int venc_hdmi_latency = 2;
unsigned long total_pixels_venc = 0;
unsigned long active_pixels_venc = 0;
unsigned long front_porch_venc = 0;
unsigned long hsync_pixels_venc = 0;
unsigned long de_h_begin = 0;
unsigned long de_h_end = 0;
unsigned long de_v_begin_even = 0;
unsigned long de_v_end_even = 0;
unsigned long de_v_begin_odd = 0;
unsigned long de_v_end_odd = 0;
unsigned long hs_begin = 0;
unsigned long hs_end = 0;
unsigned long vs_adjust = 0;
unsigned long vs_bline_evn = 0;
unsigned long vs_eline_evn = 0;
unsigned long vs_bline_odd = 0;
unsigned long vs_eline_odd = 0;
unsigned long vso_begin_evn = 0;
unsigned long vso_begin_odd = 0;
unsigned int eof_lines;
unsigned int sof_lines;
unsigned int vsync_lines;
/* Use VENCI for 480i and 576i and double HDMI pixels */
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
hdmi_repeat = true;
use_enci = true;
venc_hdmi_latency = 1;
}
if (meson_venc_hdmi_supported_vic(vic)) {
vmode = meson_venc_hdmi_get_vic_vmode(vic);
if (!vmode) {
dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
DRM_MODE_FMT "\n", __func__,
DRM_MODE_ARG(mode));
return;
}
} else {
meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
vmode = &vmode_dmt;
use_enci = false;
}
/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
if (meson_venc_hdmi_venc_repeat(vic))
venc_repeat = true;
eof_lines = mode->vsync_start - mode->vdisplay;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
eof_lines /= 2;
sof_lines = mode->vtotal - mode->vsync_end;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
sof_lines /= 2;
vsync_lines = mode->vsync_end - mode->vsync_start;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
vsync_lines /= 2;
total_pixels_venc = mode->htotal;
if (hdmi_repeat)
total_pixels_venc /= 2;
if (venc_repeat)
total_pixels_venc *= 2;
active_pixels_venc = mode->hdisplay;
if (hdmi_repeat)
active_pixels_venc /= 2;
if (venc_repeat)
active_pixels_venc *= 2;
front_porch_venc = (mode->hsync_start - mode->hdisplay);
if (hdmi_repeat)
front_porch_venc /= 2;
if (venc_repeat)
front_porch_venc *= 2;
hsync_pixels_venc = (mode->hsync_end - mode->hsync_start);
if (hdmi_repeat)
hsync_pixels_venc /= 2;
if (venc_repeat)
hsync_pixels_venc *= 2;
/* Disable VDACs */
writel_bits_relaxed(0xff, 0xff,
priv->io_base + _REG(VENC_VDAC_SETTING));
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
if (use_enci) {
unsigned int lines_f0;
unsigned int lines_f1;
/* CVBS Filter settings */
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
/* Digital Video Select : Interlace, clk27 clk, external */
writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
/* Reset Video Mode */
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
/* Horizontal sync signal output */
writel_relaxed(vmode->enci.hso_begin,
priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
writel_relaxed(vmode->enci.hso_end,
priv->io_base + _REG(ENCI_SYNC_HSO_END));
/* Vertical Sync lines */
writel_relaxed(vmode->enci.vso_even,
priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
writel_relaxed(vmode->enci.vso_odd,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel_relaxed(vmode->enci.macv_max_amp,
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
/* Video mode */
writel_relaxed(vmode->enci.video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
writel_relaxed(vmode->enci.video_mode,
priv->io_base + _REG(ENCI_VIDEO_MODE));
/* Advanced Video Mode :
* Demux shifting 0x2
* Blank line end at line17/22
* High bandwidth Luma Filter
* Low bandwidth Chroma Filter
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel(vmode->enci.sch_adjust,
priv->io_base + _REG(ENCI_VIDEO_SCH));
/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
if (vmode->enci.yc_delay)
writel_relaxed(vmode->enci.yc_delay,
priv->io_base + _REG(ENCI_YC_DELAY));
/* UNreset Interlaced TV Encoder */
writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Timings */
writel_relaxed(vmode->enci.pixel_start,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
writel_relaxed(vmode->enci.pixel_end,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
writel_relaxed(vmode->enci.top_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
writel_relaxed(vmode->enci.top_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
writel_relaxed(vmode->enci.bottom_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
writel_relaxed(vmode->enci.bottom_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
/* Select ENCI for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Interlace video enable */
writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
lines_f0 = mode->vtotal >> 1;
lines_f1 = lines_f0 + 1;
de_h_begin = modulo(readl_relaxed(priv->io_base +
_REG(ENCI_VFIFO2VD_PIXEL_START))
+ venc_hdmi_latency,
total_pixels_venc);
de_h_end = modulo(de_h_begin + active_pixels_venc,
total_pixels_venc);
writel_relaxed(de_h_begin,
priv->io_base + _REG(ENCI_DE_H_BEGIN));
writel_relaxed(de_h_end,
priv->io_base + _REG(ENCI_DE_H_END));
de_v_begin_even = readl_relaxed(priv->io_base +
_REG(ENCI_VFIFO2VD_LINE_TOP_START));
de_v_end_even = de_v_begin_even + mode->vdisplay;
de_v_begin_odd = readl_relaxed(priv->io_base +
_REG(ENCI_VFIFO2VD_LINE_BOT_START));
de_v_end_odd = de_v_begin_odd + mode->vdisplay;
writel_relaxed(de_v_begin_even,
priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
writel_relaxed(de_v_end_even,
priv->io_base + _REG(ENCI_DE_V_END_EVEN));
writel_relaxed(de_v_begin_odd,
priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
writel_relaxed(de_v_end_odd,
priv->io_base + _REG(ENCI_DE_V_END_ODD));
/* Program Hsync timing */
hs_begin = de_h_end + front_porch_venc;
if (de_h_end + front_porch_venc >= total_pixels_venc) {
hs_begin -= total_pixels_venc;
vs_adjust = 1;
} else {
hs_begin = de_h_end + front_porch_venc;
vs_adjust = 0;
}
hs_end = modulo(hs_begin + hsync_pixels_venc,
total_pixels_venc);
writel_relaxed(hs_begin,
priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
writel_relaxed(hs_end,
priv->io_base + _REG(ENCI_DVI_HSO_END));
/* Program Vsync timing for even field */
if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
vs_bline_evn = (de_v_end_odd - 1)
+ eof_lines
+ vs_adjust
- lines_f1;
vs_eline_evn = vs_bline_evn + vsync_lines;
writel_relaxed(vs_bline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
writel_relaxed(vs_eline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
writel_relaxed(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
writel_relaxed(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
} else {
vs_bline_odd = (de_v_end_odd - 1)
+ eof_lines
+ vs_adjust;
writel_relaxed(vs_bline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
writel_relaxed(hs_begin,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
if ((vs_bline_odd + vsync_lines) >= lines_f1) {
vs_eline_evn = vs_bline_odd
+ vsync_lines
- lines_f1;
writel_relaxed(vs_eline_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_EVN));
writel_relaxed(hs_begin, priv->io_base
+ _REG(ENCI_DVI_VSO_END_EVN));
} else {
vs_eline_odd = vs_bline_odd
+ vsync_lines;
writel_relaxed(vs_eline_odd, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_ODD));
writel_relaxed(hs_begin, priv->io_base
+ _REG(ENCI_DVI_VSO_END_ODD));
}
}
/* Program Vsync timing for odd field */
if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
vs_bline_odd = (de_v_end_even - 1)
+ (eof_lines + 1)
- lines_f0;
vs_eline_odd = vs_bline_odd + vsync_lines;
writel_relaxed(vs_bline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
writel_relaxed(vs_eline_odd,
priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
vso_begin_odd = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel_relaxed(vso_begin_odd,
priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
writel_relaxed(vso_begin_odd,
priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
} else {
vs_bline_evn = (de_v_end_even - 1)
+ (eof_lines + 1);
writel_relaxed(vs_bline_evn,
priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
vso_begin_evn = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel_relaxed(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_BEGIN_EVN));
if (vs_bline_evn + vsync_lines >= lines_f0) {
vs_eline_odd = vs_bline_evn
+ vsync_lines
- lines_f0;
writel_relaxed(vs_eline_odd, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_ODD));
writel_relaxed(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_END_ODD));
} else {
vs_eline_evn = vs_bline_evn + vsync_lines;
writel_relaxed(vs_eline_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_ELINE_EVN));
writel_relaxed(vso_begin_evn, priv->io_base
+ _REG(ENCI_DVI_VSO_END_EVN));
}
}
} else {
writel_relaxed(vmode->encp.dvi_settings,
priv->io_base + _REG(VENC_DVI_SETTING));
writel_relaxed(vmode->encp.video_mode,
priv->io_base + _REG(ENCP_VIDEO_MODE));
writel_relaxed(vmode->encp.video_mode_adv,
priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
if (vmode->encp.video_prog_mode_present)
writel_relaxed(vmode->encp.video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
if (vmode->encp.video_sync_mode_present)
writel_relaxed(vmode->encp.video_sync_mode,
priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
if (vmode->encp.video_yc_dly_present)
writel_relaxed(vmode->encp.video_yc_dly,
priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
if (vmode->encp.video_rgb_ctrl_present)
writel_relaxed(vmode->encp.video_rgb_ctrl,
priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
if (vmode->encp.video_filt_ctrl_present)
writel_relaxed(vmode->encp.video_filt_ctrl,
priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
if (vmode->encp.video_ofld_voav_ofst_present)
writel_relaxed(vmode->encp.video_ofld_voav_ofst,
priv->io_base
+ _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
writel_relaxed(vmode->encp.yfp1_htime,
priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
writel_relaxed(vmode->encp.yfp2_htime,
priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
writel_relaxed(vmode->encp.max_pxcnt,
priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
writel_relaxed(vmode->encp.hspuls_begin,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
writel_relaxed(vmode->encp.hspuls_end,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
writel_relaxed(vmode->encp.hspuls_switch,
priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
writel_relaxed(vmode->encp.vspuls_begin,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
writel_relaxed(vmode->encp.vspuls_end,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
writel_relaxed(vmode->encp.vspuls_bline,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
writel_relaxed(vmode->encp.vspuls_eline,
priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
if (vmode->encp.eqpuls_begin_present)
writel_relaxed(vmode->encp.eqpuls_begin,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
if (vmode->encp.eqpuls_end_present)
writel_relaxed(vmode->encp.eqpuls_end,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
if (vmode->encp.eqpuls_bline_present)
writel_relaxed(vmode->encp.eqpuls_bline,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
if (vmode->encp.eqpuls_eline_present)
writel_relaxed(vmode->encp.eqpuls_eline,
priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
writel_relaxed(vmode->encp.havon_begin,
priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
writel_relaxed(vmode->encp.havon_end,
priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
writel_relaxed(vmode->encp.vavon_bline,
priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
writel_relaxed(vmode->encp.vavon_eline,
priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
writel_relaxed(vmode->encp.hso_begin,
priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
writel_relaxed(vmode->encp.hso_end,
priv->io_base + _REG(ENCP_VIDEO_HSO_END));
writel_relaxed(vmode->encp.vso_begin,
priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
writel_relaxed(vmode->encp.vso_end,
priv->io_base + _REG(ENCP_VIDEO_VSO_END));
writel_relaxed(vmode->encp.vso_bline,
priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
if (vmode->encp.vso_eline_present)
writel_relaxed(vmode->encp.vso_eline,
priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
if (vmode->encp.sy_val_present)
writel_relaxed(vmode->encp.sy_val,
priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
if (vmode->encp.sy2_val_present)
writel_relaxed(vmode->encp.sy2_val,
priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
writel_relaxed(vmode->encp.max_lncnt,
priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));
writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
/* Set DE signals polarity is active high */
writel_bits_relaxed(BIT(14), BIT(14),
priv->io_base + _REG(ENCP_VIDEO_MODE));
/* Program DE timing */
de_h_begin = modulo(readl_relaxed(priv->io_base +
_REG(ENCP_VIDEO_HAVON_BEGIN))
+ venc_hdmi_latency,
total_pixels_venc);
de_h_end = modulo(de_h_begin + active_pixels_venc,
total_pixels_venc);
writel_relaxed(de_h_begin,
priv->io_base + _REG(ENCP_DE_H_BEGIN));
writel_relaxed(de_h_end,
priv->io_base + _REG(ENCP_DE_H_END));
/* Program DE timing for even field */
de_v_begin_even = readl_relaxed(priv->io_base
+ _REG(ENCP_VIDEO_VAVON_BLINE));
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
de_v_end_even = de_v_begin_even +
(mode->vdisplay / 2);
else
de_v_end_even = de_v_begin_even + mode->vdisplay;
writel_relaxed(de_v_begin_even,
priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
writel_relaxed(de_v_end_even,
priv->io_base + _REG(ENCP_DE_V_END_EVEN));
/* Program DE timing for odd field if needed */
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
unsigned int ofld_voav_ofst =
readl_relaxed(priv->io_base +
_REG(ENCP_VIDEO_OFLD_VOAV_OFST));
de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
+ de_v_begin_even
+ ((mode->vtotal - 1) / 2);
de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2);
writel_relaxed(de_v_begin_odd,
priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
writel_relaxed(de_v_end_odd,
priv->io_base + _REG(ENCP_DE_V_END_ODD));
}
/* Program Hsync timing */
if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
hs_begin = de_h_end
+ front_porch_venc
- total_pixels_venc;
vs_adjust = 1;
} else {
hs_begin = de_h_end
+ front_porch_venc;
vs_adjust = 0;
}
hs_end = modulo(hs_begin + hsync_pixels_venc,
total_pixels_venc);
writel_relaxed(hs_begin,
priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
writel_relaxed(hs_end,
priv->io_base + _REG(ENCP_DVI_HSO_END));
/* Program Vsync timing for even field */
if (de_v_begin_even >=
(sof_lines + vsync_lines + (1 - vs_adjust)))
vs_bline_evn = de_v_begin_even
- sof_lines
- vsync_lines
- (1 - vs_adjust);
else
vs_bline_evn = mode->vtotal
+ de_v_begin_even
- sof_lines
- vsync_lines
- (1 - vs_adjust);
vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
mode->vtotal);
writel_relaxed(vs_bline_evn,
priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
writel_relaxed(vs_eline_evn,
priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));
vso_begin_evn = hs_begin;
writel_relaxed(vso_begin_evn,
priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
writel_relaxed(vso_begin_evn,
priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));
/* Program Vsync timing for odd field if needed */
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
vs_bline_odd = (de_v_begin_odd - 1)
- sof_lines
- vsync_lines;
vs_eline_odd = (de_v_begin_odd - 1)
- vsync_lines;
vso_begin_odd = modulo(hs_begin
+ (total_pixels_venc >> 1),
total_pixels_venc);
writel_relaxed(vs_bline_odd,
priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
writel_relaxed(vs_eline_odd,
priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
writel_relaxed(vso_begin_odd,
priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
writel_relaxed(vso_begin_odd,
priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
}
/* Select ENCP for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
}
writel_relaxed((use_enci ? 1 : 2) |
(mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
(mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
4 << 5 |
(venc_repeat ? 1 << 8 : 0) |
(hdmi_repeat ? 1 << 12 : 0),
priv->io_base + _REG(VPU_HDMI_SETTING));
priv->venc.hdmi_repeat = hdmi_repeat;
priv->venc.venc_repeat = venc_repeat;
priv->venc.hdmi_use_enci = use_enci;
priv->venc.current_mode = MESON_VENC_MODE_HDMI;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
struct meson_cvbs_enci_mode *mode)
{
if (mode->mode_tag == priv->venc.current_mode)
return;
/* CVBS Filter settings */
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
/* Digital Video Select : Interlace, clk27 clk, external */
writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
/* Reset Video Mode */
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
/* Horizontal sync signal output */
writel_relaxed(mode->hso_begin,
priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
writel_relaxed(mode->hso_end,
priv->io_base + _REG(ENCI_SYNC_HSO_END));
/* Vertical Sync lines */
writel_relaxed(mode->vso_even,
priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
writel_relaxed(mode->vso_odd,
priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
/* Macrovision max amplitude change */
writel_relaxed(0x8100 + mode->macv_max_amp,
priv->io_base + _REG(ENCI_MACV_MAX_AMP));
/* Video mode */
writel_relaxed(mode->video_prog_mode,
priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
writel_relaxed(mode->video_mode,
priv->io_base + _REG(ENCI_VIDEO_MODE));
/* Advanced Video Mode :
* Demux shifting 0x2
* Blank line end at line17/22
* High bandwidth Luma Filter
* Low bandwidth Chroma Filter
* Bypass luma low pass filter
* No macrovision on CSYNC
*/
writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
/* 0x3 Y, C, and Component Y delay */
writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
/* Timings */
writel_relaxed(mode->pixel_start,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
writel_relaxed(mode->pixel_end,
priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
writel_relaxed(mode->top_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
writel_relaxed(mode->top_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
writel_relaxed(mode->bottom_field_line_start,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
writel_relaxed(mode->bottom_field_line_end,
priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
/* Internal Venc, Internal VIU Sync, Internal Vencoder */
writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
/* UNreset Interlaced TV Encoder */
writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
/* Power UP Dacs */
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
/* Video Upsampling */
writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
/* Select Interlace Y DACs */
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
/* Select ENCI for VIU */
meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
/* Enable ENCI FIFO */
writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
/* Select ENCI DACs 0, 1, 4, and 5 */
writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
/* Interlace video enable */
writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
/* Configure Video Saturation / Contrast / Brightness / Hue */
writel_relaxed(mode->video_saturation,
priv->io_base + _REG(ENCI_VIDEO_SAT));
writel_relaxed(mode->video_contrast,
priv->io_base + _REG(ENCI_VIDEO_CONT));
writel_relaxed(mode->video_brightness,
priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
writel_relaxed(mode->video_hue,
priv->io_base + _REG(ENCI_VIDEO_HUE));
/* Enable DAC0 Filter */
writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
/* 0 in Macrovision register 0 */
writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
/* Analog Synchronization and color burst value adjust */
writel_relaxed(mode->analog_sync_adj,
priv->io_base + _REG(ENCI_SYNC_ADJ));
priv->venc.current_mode = mode->mode_tag;
}
/* Returns the current ENCI field polarity */
unsigned int meson_venci_get_field(struct meson_drm *priv)
{
return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
}
void meson_venc_enable_vsync(struct meson_drm *priv)
{
writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
drm/meson: Fixes for drm_crtc_vblank_on/off support Since Linux 4.17, calls to drm_crtc_vblank_on/off are mandatory, and we get a warning when ctrc is disabled : " driver forgot to call drm_crtc_vblank_off()" But, the vsync IRQ was not totally disabled due the transient hardware state and specific interrupt line, thus adding proper IRQ masking from the HHI system control registers. The last change fixes a race condition introduced by calling the added drm_crtc_vblank_on/off when an HPD event occurs from the HDMI connector, triggering a WARN_ON() in the _atomic_begin() callback when the CRTC is disabled, thus also triggering a WARN_ON() in drm_vblank_put() : WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/meson/meson_crtc.c:157 meson_crtc_atomic_begin+0x78/0x80 [...] Call trace: meson_crtc_atomic_begin+0x78/0x80 drm_atomic_helper_commit_planes+0x140/0x218 drm_atomic_helper_commit_tail+0x38/0x80 commit_tail+0x7c/0x80 drm_atomic_helper_commit+0xdc/0x150 drm_atomic_commit+0x54/0x60 restore_fbdev_mode_atomic+0x198/0x238 restore_fbdev_mode+0x6c/0x1c0 drm_fb_helper_restore_fbdev_mode_unlocked+0x7c/0xf0 drm_fb_helper_set_par+0x34/0x60 drm_fb_helper_hotplug_event.part.28+0xb8/0xc8 drm_fbdev_client_hotplug+0xa4/0xe0 drm_client_dev_hotplug+0x90/0xe0 drm_kms_helper_hotplug_event+0x3c/0x48 drm_helper_hpd_irq_event+0x134/0x168 dw_hdmi_top_thread_irq+0x3c/0x50 [...] WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/drm_vblank.c:1026 drm_vblank_put+0xb4/0xc8 [...] Call trace: drm_vblank_put+0xb4/0xc8 drm_crtc_vblank_put+0x24/0x30 drm_atomic_helper_wait_for_vblanks.part.9+0x130/0x2b8 drm_atomic_helper_commit_tail+0x68/0x80 [...] The issue is that vblank need to be enabled in any occurrence of : - atomic_enable() - atomic_begin() and state->enable == true, which was not the case Moving the CRTC enable code to a common function and calling in one of these occurrence solves this race condition and makes sure vblank is enabled in each call to _atomic_begin() from the HPD event leading to drm_atomic_helper_commit_planes(). To Summarize : - Make sure that the CRTC code will call the drm_crtc_vblank_on()/off() - *Really* mask the Vsync IRQ - Initialize and enable vblank at the first atomic_begin()/_atomic_enable() Cc: stable@vger.kernel.org # 4.17+ Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Lyude Paul <lyude@redhat.com> [fixed typos+added cc for stable] Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181122160103.10993-1-narmstrong@baylibre.com Signed-off-by: Sean Paul <seanpaul@chromium.org>
2018-11-22 23:01:03 +07:00
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
}
void meson_venc_disable_vsync(struct meson_drm *priv)
{
drm/meson: Fixes for drm_crtc_vblank_on/off support Since Linux 4.17, calls to drm_crtc_vblank_on/off are mandatory, and we get a warning when ctrc is disabled : " driver forgot to call drm_crtc_vblank_off()" But, the vsync IRQ was not totally disabled due the transient hardware state and specific interrupt line, thus adding proper IRQ masking from the HHI system control registers. The last change fixes a race condition introduced by calling the added drm_crtc_vblank_on/off when an HPD event occurs from the HDMI connector, triggering a WARN_ON() in the _atomic_begin() callback when the CRTC is disabled, thus also triggering a WARN_ON() in drm_vblank_put() : WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/meson/meson_crtc.c:157 meson_crtc_atomic_begin+0x78/0x80 [...] Call trace: meson_crtc_atomic_begin+0x78/0x80 drm_atomic_helper_commit_planes+0x140/0x218 drm_atomic_helper_commit_tail+0x38/0x80 commit_tail+0x7c/0x80 drm_atomic_helper_commit+0xdc/0x150 drm_atomic_commit+0x54/0x60 restore_fbdev_mode_atomic+0x198/0x238 restore_fbdev_mode+0x6c/0x1c0 drm_fb_helper_restore_fbdev_mode_unlocked+0x7c/0xf0 drm_fb_helper_set_par+0x34/0x60 drm_fb_helper_hotplug_event.part.28+0xb8/0xc8 drm_fbdev_client_hotplug+0xa4/0xe0 drm_client_dev_hotplug+0x90/0xe0 drm_kms_helper_hotplug_event+0x3c/0x48 drm_helper_hpd_irq_event+0x134/0x168 dw_hdmi_top_thread_irq+0x3c/0x50 [...] WARNING: CPU: 0 PID: 1185 at drivers/gpu/drm/drm_vblank.c:1026 drm_vblank_put+0xb4/0xc8 [...] Call trace: drm_vblank_put+0xb4/0xc8 drm_crtc_vblank_put+0x24/0x30 drm_atomic_helper_wait_for_vblanks.part.9+0x130/0x2b8 drm_atomic_helper_commit_tail+0x68/0x80 [...] The issue is that vblank need to be enabled in any occurrence of : - atomic_enable() - atomic_begin() and state->enable == true, which was not the case Moving the CRTC enable code to a common function and calling in one of these occurrence solves this race condition and makes sure vblank is enabled in each call to _atomic_begin() from the HPD event leading to drm_atomic_helper_commit_planes(). To Summarize : - Make sure that the CRTC code will call the drm_crtc_vblank_on()/off() - *Really* mask the Vsync IRQ - Initialize and enable vblank at the first atomic_begin()/_atomic_enable() Cc: stable@vger.kernel.org # 4.17+ Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Lyude Paul <lyude@redhat.com> [fixed typos+added cc for stable] Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20181122160103.10993-1-narmstrong@baylibre.com Signed-off-by: Sean Paul <seanpaul@chromium.org>
2018-11-22 23:01:03 +07:00
regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
}
void meson_venc_init(struct meson_drm *priv)
{
/* Disable CVBS VDAC */
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
/* Power Down Dacs */
writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
/* Disable HDMI PHY */
regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
/* Disable HDMI */
writel_bits_relaxed(0x3, 0,
priv->io_base + _REG(VPU_HDMI_SETTING));
drm: Add support for Amlogic Meson Graphic Controller The Amlogic Meson Display controller is composed of several components : DMC|---------------VPU (Video Processing Unit)----------------|------HHI------| | vd1 _______ _____________ _________________ | | D |-------| |----| | | | | HDMI PLL | D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK | R |-------| |----| Processing | | | | | | osd2 | | | |---| Enci ----------|----|-----VDAC------| R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----| A | osd1 | | | Blenders | | Encl ----------|----|---------------| M |-------|______|----|____________| |________________| | | ___|__________________________________________________________|_______________| VIU: Video Input Unit --------------------- The Video Input Unit is in charge of the pixel scanout from the DDR memory. It fetches the frames addresses, stride and parameters from the "Canvas" memory. This part is also in charge of the CSC (Colorspace Conversion). It can handle 2 OSD Planes and 2 Video Planes. VPP: Video Post Processing -------------------------- The Video Post Processing is in charge of the scaling and blending of the various planes into a single pixel stream. There is a special "pre-blending" used by the video planes with a dedicated scaler and a "post-blending" to merge with the OSD Planes. The OSD planes also have a dedicated scaler for one of the OSD. VENC: Video Encoders -------------------- The VENC is composed of the multiple pixel encoders : - ENCI : Interlace Video encoder for CVBS and Interlace HDMI - ENCP : Progressive Video Encoder for HDMI - ENCL : LCD LVDS Encoder The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock tree and provides the scanout clock to the VPP and VIU. The ENCI is connected to a single VDAC for Composite Output. The ENCI and ENCP are connected to an on-chip HDMI Transceiver. This driver is a DRM/KMS driver using the following DRM components : - GEM-CMA - PRIME-CMA - Atomic Modesetting - FBDev-CMA For the following SoCs : - GXBB Family (S905) - GXL Family (S905X, S905D) - GXM Family (S912) The current driver only supports the CVBS PAL/NTSC output modes, but the CRTC/Planes management should support bigger modes. But Advanced Colorspace Conversion, Scaling and HDMI Modes will be added in a second time. The Device Tree bindings makes use of the endpoints video interface definitions to connect to the optional CVBS and in the future the HDMI Connector nodes. HDMI Support is planned for a next release. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2016-11-10 21:29:37 +07:00
/* Disable all encoders */
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
/* Disable VSync IRQ */
meson_venc_disable_vsync(priv);
priv->venc.current_mode = MESON_VENC_MODE_NONE;
}