[RFC 2/21] DRM: Add VIA DRM driver

James Simmons jsimmons at infradead.org
Sat Jun 8 09:44:15 PDT 2013


commit f0be3523498cd2422d95af1e5e47f51e099f90e4
Author: James Simmons <jsimmons at infradead.org>
Date:   Thu Jun 6 18:57:00 2013 -0400

    via: register setting helpers
    
    The code in the crtc_hw was written to handle to cases of
    programming the registers on the graphics card. Basic
    routines of programming of the registers already existing
    in the vga.h header in include/video that has been used
    for some of the frame buffer drivers. We add some of the
    missing bit masking and setting  routines into crtc_hw.h
    but it would be nice some day to move those over to vga.h
    itself.
    
    Addition code had been written to handle two common cases.
    The first case is that all the bits to be set are all located
    into the same register. The function to handle this is
    load_register_table. The second case is when the bits for
    a specific function are scattered across several registers.
    The load_value_to_registers handles the second case. This
    code is written such that it can be used by any other driver
    and could even be placed some where that it can be shared
    by multiple drivers.
    
    Signed-Off-by: James Simmons <jsimmons at infradead.org>

diff --git a/drivers/gpu/drm/via/crtc_hw.c b/drivers/gpu/drm/via/crtc_hw.c
new file mode 100644
index 0000000..f71c14e
--- /dev/null
+++ b/drivers/gpu/drm/via/crtc_hw.c
@@ -0,0 +1,88 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	James Simmons <jsimmons at infradead.org>
+ */
+
+#include <video/vga.h>
+#include "crtc_hw.h"
+
+/*
+ * load_register_table enables the ability to set entire
+ * tables of registers. For each register defined by the
+ * port and the index for that register is programmed
+ * with a masked value.
+ */
+void
+load_register_tables(void __iomem *regbase, struct vga_registers *regs)
+{
+	u8 cr_index, orig, reg_mask, data;
+	unsigned int i;
+	u16 port;
+
+	for (i = 0; i < regs->count; i++) {
+		reg_mask = regs->regs[i].start_bit;
+		data = regs->regs[i].end_bit;
+		cr_index = regs->regs[i].io_addr;
+		port = regs->regs[i].ioport;
+
+		vga_w(regbase, port, cr_index);
+		orig = (vga_r(regbase, port + 1) & ~reg_mask);
+		vga_w(regbase, port + 1, ((data & reg_mask) | orig));
+	}
+}
+
+/*
+ * Due to the limitation of how much data you can write to a single
+ * register we run into data that can't be written in only one register.
+ * So load_value_to_register was developed to be able to define register
+ * tables that can load different bit ranges of the data to different
+ * registers.
+ */
+void
+load_value_to_registers(void __iomem *regbase, struct vga_registers *regs,
+			unsigned int value)
+{
+	unsigned int bit_num = 0, shift_next_reg, reg_mask;
+	u8 start_index, end_index, cr_index, orig;
+	unsigned int data, i, j;
+	u16 get_bit, port;
+
+	for (i = 0; i < regs->count; i++) {
+		start_index = regs->regs[i].start_bit;
+		end_index = regs->regs[i].end_bit;
+		cr_index = regs->regs[i].io_addr;
+		port = regs->regs[i].ioport;
+		reg_mask = data = 0;
+
+		shift_next_reg = bit_num;
+		for (j = start_index; j <= end_index; j++) {
+			reg_mask = reg_mask | (1 << j);
+			get_bit = (value & (1 << bit_num));
+			data |= ((get_bit >> shift_next_reg) << start_index);
+			bit_num++;
+		}
+
+		vga_w(regbase, port, cr_index);
+		orig = (vga_r(regbase, port + 1) & ~reg_mask);
+		vga_w(regbase, port + 1, ((data & reg_mask) | orig));
+	}
+}
diff --git a/drivers/gpu/drm/via/crtc_hw.h b/drivers/gpu/drm/via/crtc_hw.h
new file mode 100644
index 0000000..a04b469
--- /dev/null
+++ b/drivers/gpu/drm/via/crtc_hw.h
@@ -0,0 +1,81 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	James Simmons <jsimmons at infradead.org>
+ */
+
+#ifndef __CRTC_HW_H__
+#define __CRTC_HW_H__
+
+struct vga_regset {
+	u16	ioport;
+	u8	io_addr;
+	u8	start_bit;
+	u8	end_bit;
+};
+
+struct vga_registers {
+	unsigned int count;
+	struct vga_regset *regs;
+};
+
+/************************************************
+ *****     Display Timing       *****
+ ************************************************/
+
+struct crtc_timings {
+	struct vga_registers htotal;
+	struct vga_registers hdisplay;
+	struct vga_registers hblank_start;
+	struct vga_registers hblank_end;
+	struct vga_registers hsync_start;
+	struct vga_registers hsync_end;
+	struct vga_registers vtotal;
+	struct vga_registers vdisplay;
+	struct vga_registers vblank_start;
+	struct vga_registers vblank_end;
+	struct vga_registers vsync_start;
+	struct vga_registers vsync_end;
+};
+
+/* Write a value to misc register with a mask */
+static inline void svga_wmisc_mask(void __iomem *regbase, u8 data, u8 mask)
+{
+	vga_w(regbase, VGA_MIS_W, (data & mask) | (vga_r(regbase, VGA_MIS_R) & ~mask));
+}
+
+/* Write a value to a sequence register with a mask */
+static inline void svga_wseq_mask(void __iomem *regbase, u8 index, u8 data, u8 mask)
+{
+	vga_wseq(regbase, index, (data & mask) | (vga_rseq(regbase, index) & ~mask));
+}
+
+/* Write a value to a CRT register with a mask */
+static inline void svga_wcrt_mask(void __iomem *regbase, u8 index, u8 data, u8 mask)
+{
+	vga_wcrt(regbase, index, (data & mask) | (vga_rcrt(regbase, index) & ~mask));
+}
+
+extern void load_register_tables(void __iomem *regbase, struct vga_registers *regs);
+extern void load_value_to_registers(void __iomem *regbase, struct vga_registers *regs,
+					unsigned int value);
+
+#endif /* __CRTC_HW_H__ */


More information about the dri-devel mailing list