brintos

brintos / linux-shallow public Read only

0
0
Text · 9.2 KiB · fbf2d76 Raw
389 lines · c
1/* SPDX-License-Identifier: GPL-2.0+ */2/*3 * Copyright (C) 2023 Loongson Technology Corporation Limited4 */5 6#ifndef __LSDC_DRV_H__7#define __LSDC_DRV_H__8 9#include <linux/pci.h>10 11#include <drm/drm_connector.h>12#include <drm/drm_crtc.h>13#include <drm/drm_device.h>14#include <drm/drm_encoder.h>15#include <drm/drm_file.h>16#include <drm/drm_plane.h>17#include <drm/ttm/ttm_device.h>18 19#include "lsdc_i2c.h"20#include "lsdc_irq.h"21#include "lsdc_gfxpll.h"22#include "lsdc_output.h"23#include "lsdc_pixpll.h"24#include "lsdc_regs.h"25 26/* Currently, all Loongson display controllers have two display pipes. */27#define LSDC_NUM_CRTC           228 29/*30 * LS7A1000/LS7A2000 chipsets function as the south & north bridges of the31 * Loongson 3 series processors, they are equipped with on-board video RAM32 * typically. While Loongson LS2K series are low cost SoCs which share the33 * system RAM as video RAM, they don't has a dedicated VRAM.34 *35 * There is only a 1:1 mapping of crtcs, encoders and connectors for the DC36 *37 * display pipe 0 = crtc0 + dvo0 + encoder0 + connector0 + cursor0 + primary038 * display pipe 1 = crtc1 + dvo1 + encoder1 + connectro1 + cursor1 + primary139 */40 41enum loongson_chip_id {42	CHIP_LS7A1000 = 0,43	CHIP_LS7A2000 = 1,44	CHIP_LS_LAST,45};46 47const struct lsdc_desc *48lsdc_device_probe(struct pci_dev *pdev, enum loongson_chip_id chip);49 50struct lsdc_kms_funcs;51 52/* DC specific */53 54struct lsdc_desc {55	u32 num_of_crtc;56	u32 max_pixel_clk;57	u32 max_width;58	u32 max_height;59	u32 num_of_hw_cursor;60	u32 hw_cursor_w;61	u32 hw_cursor_h;62	u32 pitch_align;         /* CRTC DMA alignment constraint */63	bool has_vblank_counter; /* 32 bit hw vsync counter */64 65	/* device dependent ops, dc side */66	const struct lsdc_kms_funcs *funcs;67};68 69/* GFX related resources wrangler */70 71struct loongson_gfx_desc {72	struct lsdc_desc dc;73 74	u32 conf_reg_base;75 76	/* GFXPLL shared by the DC, GMC and GPU */77	struct {78		u32 reg_offset;79		u32 reg_size;80	} gfxpll;81 82	/* Pixel PLL, per display pipe */83	struct {84		u32 reg_offset;85		u32 reg_size;86	} pixpll[LSDC_NUM_CRTC];87 88	enum loongson_chip_id chip_id;89	char model[64];90};91 92static inline const struct loongson_gfx_desc *93to_loongson_gfx(const struct lsdc_desc *dcp)94{95	return container_of_const(dcp, struct loongson_gfx_desc, dc);96};97 98struct lsdc_reg32 {99	char *name;100	u32 offset;101};102 103/* crtc hardware related ops */104 105struct lsdc_crtc;106 107struct lsdc_crtc_hw_ops {108	void (*enable)(struct lsdc_crtc *lcrtc);109	void (*disable)(struct lsdc_crtc *lcrtc);110	void (*enable_vblank)(struct lsdc_crtc *lcrtc);111	void (*disable_vblank)(struct lsdc_crtc *lcrtc);112	void (*flip)(struct lsdc_crtc *lcrtc);113	void (*clone)(struct lsdc_crtc *lcrtc);114	void (*get_scan_pos)(struct lsdc_crtc *lcrtc, int *hpos, int *vpos);115	void (*set_mode)(struct lsdc_crtc *lcrtc, const struct drm_display_mode *mode);116	void (*soft_reset)(struct lsdc_crtc *lcrtc);117	void (*reset)(struct lsdc_crtc *lcrtc);118 119	u32  (*get_vblank_counter)(struct lsdc_crtc *lcrtc);120	void (*set_dma_step)(struct lsdc_crtc *lcrtc, enum lsdc_dma_steps step);121};122 123struct lsdc_crtc {124	struct drm_crtc base;125	struct lsdc_pixpll pixpll;126	struct lsdc_device *ldev;127	const struct lsdc_crtc_hw_ops *hw_ops;128	const struct lsdc_reg32 *preg;129	unsigned int nreg;130	struct drm_info_list *p_info_list;131	unsigned int n_info_list;132	bool has_vblank;133};134 135/* primary plane hardware related ops */136 137struct lsdc_primary;138 139struct lsdc_primary_plane_ops {140	void (*update_fb_addr)(struct lsdc_primary *plane, u64 addr);141	void (*update_fb_stride)(struct lsdc_primary *plane, u32 stride);142	void (*update_fb_format)(struct lsdc_primary *plane,143				 const struct drm_format_info *format);144};145 146struct lsdc_primary {147	struct drm_plane base;148	const struct lsdc_primary_plane_ops *ops;149	struct lsdc_device *ldev;150};151 152/* cursor plane hardware related ops */153 154struct lsdc_cursor;155 156struct lsdc_cursor_plane_ops {157	void (*update_bo_addr)(struct lsdc_cursor *plane, u64 addr);158	void (*update_cfg)(struct lsdc_cursor *plane,159			   enum lsdc_cursor_size cursor_size,160			   enum lsdc_cursor_format);161	void (*update_position)(struct lsdc_cursor *plane, int x, int y);162};163 164struct lsdc_cursor {165	struct drm_plane base;166	const struct lsdc_cursor_plane_ops *ops;167	struct lsdc_device *ldev;168};169 170struct lsdc_output {171	struct drm_encoder encoder;172	struct drm_connector connector;173};174 175static inline struct lsdc_output *176connector_to_lsdc_output(struct drm_connector *connector)177{178	return container_of(connector, struct lsdc_output, connector);179}180 181static inline struct lsdc_output *182encoder_to_lsdc_output(struct drm_encoder *encoder)183{184	return container_of(encoder, struct lsdc_output, encoder);185}186 187struct lsdc_display_pipe {188	struct lsdc_crtc crtc;189	struct lsdc_primary primary;190	struct lsdc_cursor cursor;191	struct lsdc_output output;192	struct lsdc_i2c *li2c;193	unsigned int index;194};195 196static inline struct lsdc_display_pipe *197output_to_display_pipe(struct lsdc_output *output)198{199	return container_of(output, struct lsdc_display_pipe, output);200}201 202struct lsdc_kms_funcs {203	irqreturn_t (*irq_handler)(int irq, void *arg);204 205	int (*create_i2c)(struct drm_device *ddev,206			  struct lsdc_display_pipe *dispipe,207			  unsigned int index);208 209	int (*output_init)(struct drm_device *ddev,210			   struct lsdc_display_pipe *dispipe,211			   struct i2c_adapter *ddc,212			   unsigned int index);213 214	int (*cursor_plane_init)(struct drm_device *ddev,215				 struct drm_plane *plane,216				 unsigned int index);217 218	int (*primary_plane_init)(struct drm_device *ddev,219				  struct drm_plane *plane,220				  unsigned int index);221 222	int (*crtc_init)(struct drm_device *ddev,223			 struct drm_crtc *crtc,224			 struct drm_plane *primary,225			 struct drm_plane *cursor,226			 unsigned int index,227			 bool has_vblank);228};229 230static inline struct lsdc_crtc *231to_lsdc_crtc(struct drm_crtc *crtc)232{233	return container_of(crtc, struct lsdc_crtc, base);234}235 236static inline struct lsdc_display_pipe *237crtc_to_display_pipe(struct drm_crtc *crtc)238{239	return container_of(crtc, struct lsdc_display_pipe, crtc.base);240}241 242static inline struct lsdc_primary *243to_lsdc_primary(struct drm_plane *plane)244{245	return container_of(plane, struct lsdc_primary, base);246}247 248static inline struct lsdc_cursor *249to_lsdc_cursor(struct drm_plane *plane)250{251	return container_of(plane, struct lsdc_cursor, base);252}253 254struct lsdc_crtc_state {255	struct drm_crtc_state base;256	struct lsdc_pixpll_parms pparms;257};258 259struct lsdc_gem {260	/* @mutex: protect objects list */261	struct mutex mutex;262	struct list_head objects;263};264 265struct lsdc_device {266	struct drm_device base;267	struct ttm_device bdev;268 269	/* @descp: features description of the DC variant */270	const struct lsdc_desc *descp;271	struct pci_dev *dc;272	struct pci_dev *gpu;273 274	struct loongson_gfxpll *gfxpll;275 276	/* @reglock: protects concurrent access */277	spinlock_t reglock;278 279	void __iomem *reg_base;280	resource_size_t vram_base;281	resource_size_t vram_size;282 283	resource_size_t gtt_base;284	resource_size_t gtt_size;285 286	struct lsdc_display_pipe dispipe[LSDC_NUM_CRTC];287 288	struct lsdc_gem gem;289 290	u32 irq_status;291 292	/* tracking pinned memory */293	size_t vram_pinned_size;294	size_t gtt_pinned_size;295 296	/* @num_output: count the number of active display pipe */297	unsigned int num_output;298};299 300static inline struct lsdc_device *tdev_to_ldev(struct ttm_device *bdev)301{302	return container_of(bdev, struct lsdc_device, bdev);303}304 305static inline struct lsdc_device *to_lsdc(struct drm_device *ddev)306{307	return container_of(ddev, struct lsdc_device, base);308}309 310static inline struct lsdc_crtc_state *311to_lsdc_crtc_state(struct drm_crtc_state *base)312{313	return container_of(base, struct lsdc_crtc_state, base);314}315 316void lsdc_debugfs_init(struct drm_minor *minor);317 318int ls7a1000_crtc_init(struct drm_device *ddev,319		       struct drm_crtc *crtc,320		       struct drm_plane *primary,321		       struct drm_plane *cursor,322		       unsigned int index,323		       bool no_vblank);324 325int ls7a2000_crtc_init(struct drm_device *ddev,326		       struct drm_crtc *crtc,327		       struct drm_plane *primary,328		       struct drm_plane *cursor,329		       unsigned int index,330		       bool no_vblank);331 332int lsdc_primary_plane_init(struct drm_device *ddev,333			    struct drm_plane *plane,334			    unsigned int index);335 336int ls7a1000_cursor_plane_init(struct drm_device *ddev,337			       struct drm_plane *plane,338			       unsigned int index);339 340int ls7a2000_cursor_plane_init(struct drm_device *ddev,341			       struct drm_plane *plane,342			       unsigned int index);343 344/* Registers access helpers */345 346static inline u32 lsdc_rreg32(struct lsdc_device *ldev, u32 offset)347{348	return readl(ldev->reg_base + offset);349}350 351static inline void lsdc_wreg32(struct lsdc_device *ldev, u32 offset, u32 val)352{353	writel(val, ldev->reg_base + offset);354}355 356static inline void lsdc_ureg32_set(struct lsdc_device *ldev,357				   u32 offset,358				   u32 mask)359{360	void __iomem *addr = ldev->reg_base + offset;361	u32 val = readl(addr);362 363	writel(val | mask, addr);364}365 366static inline void lsdc_ureg32_clr(struct lsdc_device *ldev,367				   u32 offset,368				   u32 mask)369{370	void __iomem *addr = ldev->reg_base + offset;371	u32 val = readl(addr);372 373	writel(val & ~mask, addr);374}375 376static inline u32 lsdc_pipe_rreg32(struct lsdc_device *ldev,377				   u32 offset, u32 pipe)378{379	return readl(ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);380}381 382static inline void lsdc_pipe_wreg32(struct lsdc_device *ldev,383				    u32 offset, u32 pipe, u32 val)384{385	writel(val, ldev->reg_base + offset + pipe * CRTC_PIPE_OFFSET);386}387 388#endif389