brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · 31624c9 Raw
203 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#include <linux/pci.h>4 5#include <drm/drm_atomic.h>6#include <drm/drm_atomic_helper.h>7#include <drm/drm_drv.h>8#include <drm/drm_gem_atomic_helper.h>9#include <drm/drm_probe_helper.h>10 11#include "mgag200_drv.h"12 13static void mgag200_g200ew3_init_registers(struct mga_device *mdev)14{15	mgag200_g200wb_init_registers(mdev); // same as G200WB16 17	WREG_ECRT(0x34, 0x5); // G200EW3 specific18}19 20/*21 * PIXPLLC22 */23 24static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc,25						struct drm_atomic_state *new_state)26{27	static const unsigned int vcomax = 800000;28	static const unsigned int vcomin = 400000;29	static const unsigned int pllreffreq = 25000;30 31	struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);32	struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);33	long clock = new_crtc_state->mode.clock;34	struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;35	unsigned int delta, tmpdelta;36	unsigned int testp, testm, testn, testp2;37	unsigned int p, m, n, s;38	unsigned int computed;39 40	m = n = p = s = 0;41	delta = 0xffffffff;42 43	for (testp = 1; testp < 8; testp++) {44		for (testp2 = 1; testp2 < 8; testp2++) {45			if (testp < testp2)46				continue;47			if ((clock * testp * testp2) > vcomax)48				continue;49			if ((clock * testp * testp2) < vcomin)50				continue;51			for (testm = 1; testm < 26; testm++) {52				for (testn = 32; testn < 2048 ; testn++) {53					computed = (pllreffreq * testn) / (testm * testp * testp2);54					if (computed > clock)55						tmpdelta = computed - clock;56					else57						tmpdelta = clock - computed;58					if (tmpdelta < delta) {59						delta = tmpdelta;60						m = testm + 1;61						n = testn + 1;62						p = testp + 1;63						s = testp2;64					}65				}66			}67		}68	}69 70	pixpllc->m = m;71	pixpllc->n = n;72	pixpllc->p = p;73	pixpllc->s = s;74 75	return 0;76}77 78/*79 * Mode-setting pipeline80 */81 82static const struct drm_plane_helper_funcs mgag200_g200ew3_primary_plane_helper_funcs = {83	MGAG200_PRIMARY_PLANE_HELPER_FUNCS,84};85 86static const struct drm_plane_funcs mgag200_g200ew3_primary_plane_funcs = {87	MGAG200_PRIMARY_PLANE_FUNCS,88};89 90static const struct drm_crtc_helper_funcs mgag200_g200ew3_crtc_helper_funcs = {91	MGAG200_CRTC_HELPER_FUNCS,92};93 94static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {95	MGAG200_CRTC_FUNCS,96};97 98static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)99{100	struct drm_device *dev = &mdev->base;101	struct drm_plane *primary_plane = &mdev->primary_plane;102	struct drm_crtc *crtc = &mdev->crtc;103	int ret;104 105	ret = drm_universal_plane_init(dev, primary_plane, 0,106				       &mgag200_g200ew3_primary_plane_funcs,107				       mgag200_primary_plane_formats,108				       mgag200_primary_plane_formats_size,109				       mgag200_primary_plane_fmtmods,110				       DRM_PLANE_TYPE_PRIMARY, NULL);111	if (ret) {112		drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);113		return ret;114	}115	drm_plane_helper_add(primary_plane, &mgag200_g200ew3_primary_plane_helper_funcs);116	drm_plane_enable_fb_damage_clips(primary_plane);117 118	ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,119					&mgag200_g200ew3_crtc_funcs, NULL);120	if (ret) {121		drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);122		return ret;123	}124	drm_crtc_helper_add(crtc, &mgag200_g200ew3_crtc_helper_funcs);125 126	/* FIXME: legacy gamma tables, but atomic gamma doesn't work without */127	drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);128	drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);129 130	ret = mgag200_vga_bmc_output_init(mdev);131	if (ret)132		return ret;133 134	return 0;135}136 137/*138 * DRM device139 */140 141static const struct mgag200_device_info mgag200_g200ew3_device_info =142	MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);143 144static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {145	.pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check,146	.pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB147};148 149static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)150{151	resource_size_t vram_size = resource_size(mdev->vram_res);152 153	if (vram_size >= 0x1000000)154		vram_size = vram_size - 0x400000;155	return mgag200_probe_vram(mdev->vram, vram_size);156}157 158struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,159						 const struct drm_driver *drv)160{161	struct mga_device *mdev;162	struct drm_device *dev;163	resource_size_t vram_available;164	int ret;165 166	mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);167	if (IS_ERR(mdev))168		return mdev;169	dev = &mdev->base;170 171	pci_set_drvdata(pdev, dev);172 173	ret = mgag200_init_pci_options(pdev, 0x41049120, 0x0000b000);174	if (ret)175		return ERR_PTR(ret);176 177	ret = mgag200_device_preinit(mdev);178	if (ret)179		return ERR_PTR(ret);180 181	ret = mgag200_device_init(mdev, &mgag200_g200ew3_device_info,182				  &mgag200_g200ew3_device_funcs);183	if (ret)184		return ERR_PTR(ret);185 186	mgag200_g200ew3_init_registers(mdev);187 188	vram_available = mgag200_g200ew3_device_probe_vram(mdev);189 190	ret = mgag200_mode_config_init(mdev, vram_available);191	if (ret)192		return ERR_PTR(ret);193 194	ret = mgag200_g200ew3_pipeline_init(mdev);195	if (ret)196		return ERR_PTR(ret);197 198	drm_mode_config_reset(dev);199	drm_kms_helper_poll_init(dev);200 201	return mdev;202}203