mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
05ecc67835
The LCDIF controller as present in i.MX28/i.MX6SX/i.MX8M Mini/Nano has CRC_STAT register, which contains CRC32 of the frame as it was clocked out of the DPI interface of the LCDIF. This is most likely meant as a functional safety feature. Unfortunately, there is zero documentation on how the CRC32 is calculated, there is no documentation of the polynomial, the init value, nor on which data is the checksum applied. By applying brute-force on 8 pixel / 2 line frame, which is the minimum size LCDIF would work with, it turns out the polynomial is CRC32_POLY_LE 0xedb88320 , init value is 0xffffffff , the input data are bitrev32() of the entire frame and the resulting CRC has to be also bitrev32()ed. Doing this calculation in kernel for each frame is unrealistic due to the CPU demand, so attach the CRC collected from hardware to a frame instead. The DRM subsystem already has an interface for this purpose and the CRC can be accessed e.g. via debugfs: " $ echo auto > /sys/kernel/debug/dri/1/crtc-0/crc/control $ cat /sys/kernel/debug/dri/1/crtc-0/crc/data 0x0000408c 0xa4e5cdd8 0x0000408d 0x72f537b4 " The per-frame CRC can be used by userspace e.g. during automated testing, to verify that whatever buffer was sent to be scanned out was actually scanned out of the LCDIF correctly. Acked-by: Lucas Stach <l.stach@pengutronix.de> Acked-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Alexander Stein <alexander.stein@ew.tq-group.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Peng Fan <peng.fan@nxp.com> Cc: Robby Cai <robby.cai@nxp.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220429212313.305556-1-marex@denx.de
64 lines
1.3 KiB
C
64 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
|
|
*
|
|
* i.MX23/i.MX28/i.MX6SX MXSFB LCD controller driver.
|
|
*/
|
|
|
|
#ifndef __MXSFB_DRV_H__
|
|
#define __MXSFB_DRV_H__
|
|
|
|
#include <drm/drm_crtc.h>
|
|
#include <drm/drm_device.h>
|
|
#include <drm/drm_encoder.h>
|
|
#include <drm/drm_plane.h>
|
|
|
|
struct clk;
|
|
|
|
struct mxsfb_devdata {
|
|
unsigned int transfer_count;
|
|
unsigned int cur_buf;
|
|
unsigned int next_buf;
|
|
unsigned int hs_wdth_mask;
|
|
unsigned int hs_wdth_shift;
|
|
bool has_overlay;
|
|
bool has_ctrl2;
|
|
bool has_crc32;
|
|
};
|
|
|
|
struct mxsfb_drm_private {
|
|
const struct mxsfb_devdata *devdata;
|
|
|
|
void __iomem *base; /* registers */
|
|
struct clk *clk;
|
|
struct clk *clk_axi;
|
|
struct clk *clk_disp_axi;
|
|
|
|
unsigned int irq;
|
|
|
|
struct drm_device *drm;
|
|
struct {
|
|
struct drm_plane primary;
|
|
struct drm_plane overlay;
|
|
} planes;
|
|
struct drm_crtc crtc;
|
|
struct drm_encoder encoder;
|
|
struct drm_connector *connector;
|
|
struct drm_bridge *bridge;
|
|
|
|
bool crc_active;
|
|
};
|
|
|
|
static inline struct mxsfb_drm_private *
|
|
to_mxsfb_drm_private(struct drm_device *drm)
|
|
{
|
|
return drm->dev_private;
|
|
}
|
|
|
|
void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
|
|
void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
|
|
|
|
int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb);
|
|
|
|
#endif /* __MXSFB_DRV_H__ */
|