Module Name: src
Committed By: jmcneill
Date: Sun Mar 22 13:53:33 UTC 2015
Modified Files:
src/sys/arch/arm/amlogic: amlogic_genfb.c amlogic_vpureg.h
src/sys/arch/evbarm/amlogic: amlogic_machdep.c
Log Message:
Use the hardware scaler to do overscan compensation. You can set the
scaling value as a percentage in two ways -- either as a kernel cmdline
parameter (fb.scale=<pct>) or at runtime with sysctl (hw.genfb0.scale=<pct>).
Setting scale=100 disables the scaler, any other value enables it. For
the cheap TV on my desk, scale=95 gives me a fully visible framebuffer.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/amlogic/amlogic_genfb.c \
src/sys/arch/arm/amlogic/amlogic_vpureg.h
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/evbarm/amlogic/amlogic_machdep.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/amlogic/amlogic_genfb.c
diff -u src/sys/arch/arm/amlogic/amlogic_genfb.c:1.1 src/sys/arch/arm/amlogic/amlogic_genfb.c:1.2
--- src/sys/arch/arm/amlogic/amlogic_genfb.c:1.1 Sat Mar 21 01:17:00 2015
+++ src/sys/arch/arm/amlogic/amlogic_genfb.c Sun Mar 22 13:53:33 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: amlogic_genfb.c,v 1.1 2015/03/21 01:17:00 jmcneill Exp $ */
+/* $NetBSD: amlogic_genfb.c,v 1.2 2015/03/22 13:53:33 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amlogic_genfb.c,v 1.1 2015/03/21 01:17:00 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amlogic_genfb.c,v 1.2 2015/03/22 13:53:33 jmcneill Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: amlogic_genf
#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kmem.h>
+#include <sys/sysctl.h>
#include <arm/amlogic/amlogic_reg.h>
#include <arm/amlogic/amlogic_var.h>
@@ -60,6 +61,10 @@ static const struct amlogic_genfb_vic2mo
{ 3, 720, 480 },
{ 4, 1280, 720 },
{ 5, 1920, 1080 },
+ { 6, 720, 480 },
+ { 7, 720, 480 },
+ { 8, 720, 240 },
+ { 9, 720, 240 },
{ 16, 1920, 1080 },
{ 17, 720, 576 },
{ 18, 720, 576 },
@@ -75,17 +80,24 @@ static const struct amlogic_genfb_vic2mo
struct amlogic_genfb_softc {
struct genfb_softc sc_gen;
bus_space_tag_t sc_bst;
- bus_space_handle_t sc_bsh;
+ bus_space_handle_t sc_cav_bsh;
bus_space_handle_t sc_hdmi_bsh;
bus_space_handle_t sc_vpu_bsh;
bus_dma_tag_t sc_dmat;
+ kmutex_t sc_lock;
+
+ u_int sc_scale;
+
bus_dma_segment_t sc_dmasegs[1];
bus_size_t sc_dmasize;
bus_dmamap_t sc_dmamap;
void *sc_dmap;
uint32_t sc_wstype;
+
+ struct sysctllog *sc_sysctllog;
+ int sc_node_scale;
};
static int amlogic_genfb_match(device_t, cfdata_t, void *);
@@ -95,9 +107,15 @@ static int amlogic_genfb_ioctl(void *, v
static paddr_t amlogic_genfb_mmap(void *, void *, off_t, int);
static bool amlogic_genfb_shutdown(device_t, int);
-static void amlogic_genfb_probe(struct amlogic_genfb_softc *);
+static void amlogic_genfb_canvas_config(struct amlogic_genfb_softc *);
+static void amlogic_genfb_osd_config(struct amlogic_genfb_softc *);
+static void amlogic_genfb_scaler_config(struct amlogic_genfb_softc *);
+
+static void amlogic_genfb_init(struct amlogic_genfb_softc *);
static int amlogic_genfb_alloc_videomem(struct amlogic_genfb_softc *);
+static int amlogic_genfb_scale_helper(SYSCTLFN_PROTO);
+
void amlogic_genfb_set_console_dev(device_t);
void amlogic_genfb_ddb_trap_callback(int);
@@ -131,6 +149,11 @@ amlogic_genfb_hdmi_write_4(struct amlogi
#define VPU_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_vpu_bsh, (reg), (val))
+#define CAV_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_cav_bsh, (reg))
+#define CAV_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_cav_bsh, (reg), (val))
+
static int
amlogic_genfb_match(device_t parent, cfdata_t match, void *aux)
{
@@ -152,13 +175,14 @@ amlogic_genfb_attach(device_t parent, de
sc->sc_bst = aio->aio_core_bst;
sc->sc_dmat = aio->aio_dmat;
bus_space_subregion(aio->aio_core_bst, aio->aio_bsh,
- loc->loc_offset, loc->loc_size, &sc->sc_bsh);
+ loc->loc_offset, loc->loc_size, &sc->sc_cav_bsh);
bus_space_subregion(aio->aio_core_bst, aio->aio_bsh,
AMLOGIC_HDMI_OFFSET, AMLOGIC_HDMI_SIZE, &sc->sc_hdmi_bsh);
bus_space_subregion(aio->aio_core_bst, aio->aio_bsh,
AMLOGIC_VPU_OFFSET, AMLOGIC_VPU_SIZE, &sc->sc_vpu_bsh);
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
- amlogic_genfb_probe(sc);
+ amlogic_genfb_init(sc);
sc->sc_wstype = WSDISPLAY_TYPE_MESON;
prop_dictionary_get_bool(dict, "is_console", &is_console);
@@ -236,40 +260,207 @@ amlogic_genfb_shutdown(device_t self, in
}
static void
-amlogic_genfb_probe(struct amlogic_genfb_softc *sc)
+amlogic_genfb_canvas_config(struct amlogic_genfb_softc *sc)
{
prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
- u_int width = 0, height = 0, i;
+ const paddr_t pa = sc->sc_dmamap->dm_segs[0].ds_addr;
uint32_t datal, datah, addr;
- uint32_t w1, w2, w3, w4;
- int error;
+ u_int width, height;
- datal = bus_space_read_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_DATAL_REG);
- datah = bus_space_read_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_DATAH_REG);
- addr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_ADDR_REG);
-
- w1 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W1_REG);
- w2 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W2_REG);
- w3 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W3_REG);
- w4 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W4_REG);
-
-#if 0
- const u_int w = (__SHIFTOUT(datal, DC_CAV_LUT_DATAL_WIDTH_L) |
- (__SHIFTOUT(datah, DC_CAV_LUT_DATAH_WIDTH_H) << 3)) << 3;
- const u_int h = __SHIFTOUT(datah, DC_CAV_LUT_DATAH_HEIGHT);
-#endif
+ prop_dictionary_get_uint32(cfg, "width", &width);
+ prop_dictionary_get_uint32(cfg, "height", &height);
- /* VIC is in AVI InfoFrame PB4. */
- const uint32_t vic = HDMI_READ(sc, HDMITX_AVI_INFO_ADDR + 4) & 0x7f;
+ const uint32_t w = (width * 3) >> 3;
+ const uint32_t h = height;
+
+ datal = CAV_READ(sc, DC_CAV_LUT_DATAL_REG);
+ datah = CAV_READ(sc, DC_CAV_LUT_DATAH_REG);
+ addr = CAV_READ(sc, DC_CAV_LUT_ADDR_REG);
+
+ datal &= ~DC_CAV_LUT_DATAL_WIDTH_L;
+ datal |= __SHIFTIN(w & 7, DC_CAV_LUT_DATAL_WIDTH_L);
+ datal &= ~DC_CAV_LUT_DATAL_FBADDR;
+ datal |= __SHIFTIN(pa >> 3, DC_CAV_LUT_DATAL_FBADDR);
+ CAV_WRITE(sc, DC_CAV_LUT_DATAL_REG, datal);
+
+ datah &= ~DC_CAV_LUT_DATAH_BLKMODE;
+ datah |= __SHIFTIN(DC_CAV_LUT_DATAH_BLKMODE_LINEAR,
+ DC_CAV_LUT_DATAH_BLKMODE);
+ datah &= ~DC_CAV_LUT_DATAH_WIDTH_H;
+ datah |= __SHIFTIN(w >> 3, DC_CAV_LUT_DATAH_WIDTH_H);
+ datah &= ~DC_CAV_LUT_DATAH_HEIGHT;
+ datah |= __SHIFTIN(h, DC_CAV_LUT_DATAH_HEIGHT);
+ CAV_WRITE(sc, DC_CAV_LUT_DATAH_REG, datah);
+
+ addr |= DC_CAV_LUT_ADDR_WR_EN;
+ CAV_WRITE(sc, DC_CAV_LUT_ADDR_REG, addr);
+}
+
+static void
+amlogic_genfb_osd_config(struct amlogic_genfb_softc *sc)
+{
+ prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+ uint32_t w0, w1, w2, w3, w4;
+ u_int width, height;
+
+ prop_dictionary_get_uint32(cfg, "width", &width);
+ prop_dictionary_get_uint32(cfg, "height", &height);
+ w0 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W0_REG);
+ w0 &= ~VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE;
+ w0 |= __SHIFTIN(7, VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE);
+ w0 |= VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN;
+ w0 &= ~VIU_OSD_BLK_CFG_W0_INTERP_CTRL;
+ w0 &= ~VIU_OSD_BLK_CFG_W0_INTERLACE_EN;
+ w0 |= VIU_OSD_BLK_CFG_W0_RGB_EN;
+ w0 &= ~VIU_OSD_BLK_CFG_W0_COLOR_MATRIX;
+ VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W0_REG, w0);
+
+ w1 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W1_X_END) |
+ __SHIFTIN(0, VIU_OSD_BLK_CFG_W1_X_START);
+ w2 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W2_Y_END) |
+ __SHIFTIN(0, VIU_OSD_BLK_CFG_W2_Y_START);
+ w3 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W3_H_END) |
+ __SHIFTIN(0, VIU_OSD_BLK_CFG_W3_H_START);
+ w4 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W4_V_END) |
+ __SHIFTIN(0, VIU_OSD_BLK_CFG_W4_V_START);
+
+ VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W1_REG, w1);
+ VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W2_REG, w2);
+ VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W3_REG, w3);
+ VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W4_REG, w4);
+}
+
+static void
+amlogic_genfb_scaler_config(struct amlogic_genfb_softc *sc)
+{
+ prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+ uint32_t scctl, sci_wh, sco_h, sco_v, hsc, vsc, hps, vps, hip, vip;
+ u_int width, height;
+
+ prop_dictionary_get_uint32(cfg, "width", &width);
+ prop_dictionary_get_uint32(cfg, "height", &height);
+
+ const u_int scale = sc->sc_scale;
+ const u_int dst_w = (width * scale) / 100;
+ const u_int dst_h = (height * scale) / 100;
+ const u_int margin_w = (width - dst_w) / 2;
+ const u_int margin_h = (height - dst_h) / 2;
+ const bool interlace_p = false; /* TODO */
+ const bool scale_p = scale != 100;
+
+ VPU_WRITE(sc, VPP_OSD_SC_DUMMY_DATA_REG, 0x00808000);
+
+ scctl = VPU_READ(sc, VPP_OSD_SC_CTRL0_REG);
+ scctl |= VPP_OSD_SC_CTRL0_OSD_SC_PATH_EN;
+ scctl &= ~VPP_OSD_SC_CTRL0_OSD_SC_SEL;
+ scctl |= __SHIFTIN(1, VPP_OSD_SC_CTRL0_OSD_SC_SEL); /* OSD2 */
+ scctl &= ~VPP_OSD_SC_CTRL0_DEFAULT_ALPHA;
+ scctl |= __SHIFTIN(0, VPP_OSD_SC_CTRL0_DEFAULT_ALPHA);
+ VPU_WRITE(sc, VPP_OSD_SC_CTRL0_REG, scctl);
+
+ sci_wh = __SHIFTIN(width - 1, VPP_OSD_SCI_WH_M1_WIDTH) |
+ __SHIFTIN(height - 1, VPP_OSD_SCI_WH_M1_HEIGHT);
+ sco_h = __SHIFTIN(margin_w, VPP_OSD_SCO_H_START) |
+ __SHIFTIN(width - margin_w - 1, VPP_OSD_SCO_H_END);
+ sco_v = __SHIFTIN(margin_h, VPP_OSD_SCO_V_START) |
+ __SHIFTIN(height - margin_h - 1, VPP_OSD_SCO_V_END);
+
+ VPU_WRITE(sc, VPP_OSD_SCI_WH_M1_REG, sci_wh);
+ VPU_WRITE(sc, VPP_OSD_SCO_H_REG, sco_h);
+ VPU_WRITE(sc, VPP_OSD_SCO_V_REG, sco_v);
+
+ /* horizontal scaling */
+ hsc = VPU_READ(sc, VPP_OSD_HSC_CTRL0_REG);
+ if (scale_p) {
+ hsc &= ~VPP_OSD_HSC_CTRL0_BANK_LENGTH;
+ hsc |= __SHIFTIN(4, VPP_OSD_HSC_CTRL0_BANK_LENGTH);
+ hsc &= ~VPP_OSD_HSC_CTRL0_INI_RCV_NUM0;
+ hsc |= __SHIFTIN(4, VPP_OSD_HSC_CTRL0_INI_RCV_NUM0);
+ hsc &= ~VPP_OSD_HSC_CTRL0_RPT_P0_NUM0;
+ hsc |= __SHIFTIN(1, VPP_OSD_HSC_CTRL0_RPT_P0_NUM0);
+ hsc |= VPP_OSD_HSC_CTRL0_HSCALE_EN;
+ } else {
+ hsc &= ~VPP_OSD_HSC_CTRL0_HSCALE_EN;
+ }
+ VPU_WRITE(sc, VPP_OSD_HSC_CTRL0_REG, hsc);
+
+ /* vertical scaling */
+ vsc = VPU_READ(sc, VPP_OSD_VSC_CTRL0_REG);
+ if (scale_p) {
+ vsc &= ~VPP_OSD_VSC_CTRL0_BANK_LENGTH;
+ vsc |= __SHIFTIN(4, VPP_OSD_VSC_CTRL0_BANK_LENGTH);
+ vsc &= ~VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0;
+ vsc |= __SHIFTIN(4, VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0);
+ vsc &= ~VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0;
+ vsc |= __SHIFTIN(1, VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0);
+ vsc &= ~VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0;
+ vsc &= ~VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0;
+ vsc &= ~VPP_OSC_VSC_CTRL0_INTERLACE;
+ if (interlace_p) {
+ /* interlace */
+ vsc |= VPP_OSC_VSC_CTRL0_INTERLACE;
+ vsc |= __SHIFTIN(6, VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0);
+ vsc |= __SHIFTIN(2, VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0);
+ }
+ vsc |= VPP_OSD_VSC_CTRL0_VSCALE_EN;
+ } else {
+ vsc &= ~VPP_OSD_VSC_CTRL0_VSCALE_EN;
+ }
+ VPU_WRITE(sc, VPP_OSD_VSC_CTRL0_REG, vsc);
+
+ /* free scale enable */
+ if (scale_p) {
+ const u_int hf_phase_step = ((width << 18) / dst_w) << 6;
+ const u_int vf_phase_step = ((height << 20) / dst_h) << 4;
+ const u_int bot_ini_phase =
+ interlace_p ? ((vf_phase_step / 2) >> 8) : 0;
+
+ hps = VPU_READ(sc, VPP_OSD_HSC_PHASE_STEP_REG);
+ hps &= ~VPP_OSD_HSC_PHASE_STEP_FORMAT;
+ hps |= __SHIFTIN(hf_phase_step, VPP_OSD_HSC_PHASE_STEP_FORMAT);
+ VPU_WRITE(sc, VPP_OSD_HSC_PHASE_STEP_REG, hps);
+
+ hip = VPU_READ(sc, VPP_OSD_HSC_INI_PHASE_REG);
+ hip &= ~VPP_OSD_HSC_INI_PHASE_1;
+ VPU_WRITE(sc, VPP_OSD_HSC_INI_PHASE_REG, hip);
+
+ vps = VPU_READ(sc, VPP_OSD_VSC_PHASE_STEP_REG);
+ vps &= ~VPP_OSD_VSC_PHASE_STEP_FORMAT;
+ vps |= __SHIFTIN(hf_phase_step, VPP_OSD_VSC_PHASE_STEP_FORMAT);
+ VPU_WRITE(sc, VPP_OSD_VSC_PHASE_STEP_REG, vps);
+
+ vip = VPU_READ(sc, VPP_OSD_VSC_INI_PHASE_REG);
+ vip &= ~VPP_OSD_VSC_INI_PHASE_1;
+ vip |= __SHIFTIN(0, VPP_OSD_VSC_INI_PHASE_1);
+ vip &= ~VPP_OSD_VSC_INI_PHASE_0;
+ vip |= __SHIFTIN(bot_ini_phase, VPP_OSD_VSC_INI_PHASE_0);
+ VPU_WRITE(sc, VPP_OSD_VSC_INI_PHASE_REG, vip);
+ }
+}
+
+static void
+amlogic_genfb_init(struct amlogic_genfb_softc *sc)
+{
+ prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+ const struct sysctlnode *node, *devnode;
+ u_int width = 0, height = 0, i, scale = 100;
+ int error;
+
+ /*
+ * Firmware has (maybe) setup HDMI TX for us. Read the VIC from
+ * the HDMI AVI InfoFrame (bits 6:0 in PB4) and map that to a
+ * framebuffer geometry.
+ */
+ const uint32_t vic = HDMI_READ(sc, HDMITX_AVI_INFO_ADDR + 4) & 0x7f;
for (i = 0; i < __arraycount(amlogic_genfb_modes); i++) {
if (amlogic_genfb_modes[i].vic == vic) {
aprint_debug(" [HDMI VIC %d]", vic);
width = amlogic_genfb_modes[i].width;
height = amlogic_genfb_modes[i].height;
+ break;
}
}
-
if (width == 0 || height == 0) {
aprint_error(" [UNSUPPORTED HDMI VIC %d]", vic);
return;
@@ -279,54 +470,91 @@ amlogic_genfb_probe(struct amlogic_genfb
sc->sc_dmasize = (fbsize + 3) & ~3;
error = amlogic_genfb_alloc_videomem(sc);
- if (error == 0) {
- const paddr_t pa = sc->sc_dmamap->dm_segs[0].ds_addr;
- const uint32_t w = width * 3;
- const uint32_t h = height;
-
- datal &= ~DC_CAV_LUT_DATAL_WIDTH_L;
- datal |= __SHIFTIN(w >> 3, DC_CAV_LUT_DATAL_WIDTH_L);
- datal &= ~DC_CAV_LUT_DATAL_FBADDR;
- datal |= __SHIFTIN(pa >> 3, DC_CAV_LUT_DATAL_FBADDR);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_DATAL_REG,
- datal);
-
- datah &= ~DC_CAV_LUT_DATAH_BLKMODE;
- datah |= __SHIFTIN(DC_CAV_LUT_DATAH_BLKMODE_LINEAR,
- DC_CAV_LUT_DATAH_BLKMODE);
- datah &= ~DC_CAV_LUT_DATAH_WIDTH_H;
- datah |= __SHIFTIN(w >> 6, DC_CAV_LUT_DATAH_WIDTH_H);
- datah &= ~DC_CAV_LUT_DATAH_HEIGHT;
- datah |= __SHIFTIN(h, DC_CAV_LUT_DATAH_HEIGHT);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_DATAH_REG,
- datah);
-
- addr |= DC_CAV_LUT_ADDR_WR_EN;
- bus_space_write_4(sc->sc_bst, sc->sc_bsh, DC_CAV_LUT_ADDR_REG,
- addr);
-
- w1 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W1_X_END);
- w2 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W2_Y_END);
- w3 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W3_H_END);
- w4 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W4_V_END);
-
- VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W1_REG, w1);
- VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W2_REG, w2);
- VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W3_REG, w3);
- VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W4_REG, w4);
-
- prop_dictionary_set_uint32(cfg, "width", width);
- prop_dictionary_set_uint32(cfg, "height", height);
- prop_dictionary_set_uint8(cfg, "depth", 24);
- prop_dictionary_set_uint16(cfg, "linebytes", width * 3);
- prop_dictionary_set_uint32(cfg, "address", 0);
- prop_dictionary_set_uint32(cfg, "virtual_address",
- (uintptr_t)sc->sc_dmap);
- } else {
+ if (error) {
aprint_error_dev(sc->sc_gen.sc_dev,
"failed to allocate %u bytes of video memory: %d\n",
(u_int)sc->sc_dmasize, error);
+ return;
+ }
+
+ prop_dictionary_get_uint32(cfg, "scale", &scale);
+ if (scale > 100) {
+ scale = 100;
+ } else if (scale < 10) {
+ scale = 10;
}
+ sc->sc_scale = scale;
+
+ prop_dictionary_set_uint32(cfg, "width", width);
+ prop_dictionary_set_uint32(cfg, "height", height);
+ prop_dictionary_set_uint8(cfg, "depth", 24);
+ prop_dictionary_set_uint16(cfg, "linebytes", width * 3);
+ prop_dictionary_set_uint32(cfg, "address", 0);
+ prop_dictionary_set_uint32(cfg, "virtual_address",
+ (uintptr_t)sc->sc_dmap);
+
+ amlogic_genfb_canvas_config(sc);
+ amlogic_genfb_osd_config(sc);
+ amlogic_genfb_scaler_config(sc);
+
+ /* sysctl setup */
+ error = sysctl_createv(&sc->sc_sysctllog, 0, NULL, &node,
+ CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
+ NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
+ if (error)
+ goto sysctl_failed;
+ error = sysctl_createv(&sc->sc_sysctllog, 0, &node, &devnode,
+ 0, CTLTYPE_NODE, device_xname(sc->sc_gen.sc_dev), NULL,
+ NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
+ if (error)
+ goto sysctl_failed;
+ error = sysctl_createv(&sc->sc_sysctllog, 0, &devnode, &node,
+ CTLFLAG_READWRITE, CTLTYPE_INT, "scale", NULL,
+ amlogic_genfb_scale_helper, 0, (void *)sc, 0,
+ CTL_CREATE, CTL_EOL);
+ if (error)
+ goto sysctl_failed;
+ sc->sc_node_scale = node->sysctl_num;
+
+ return;
+
+sysctl_failed:
+ aprint_error_dev(sc->sc_gen.sc_dev,
+ "couldn't create sysctl nodes (%d)\n", error);
+ sysctl_teardown(&sc->sc_sysctllog);
+}
+
+static int
+amlogic_genfb_scale_helper(SYSCTLFN_ARGS)
+{
+ struct amlogic_genfb_softc *sc;
+ struct sysctlnode node;
+ int scale, oldscale, error;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ scale = oldscale = sc->sc_scale;
+ node.sysctl_data = &scale;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ if (scale > 100) {
+ scale = 100;
+ } else if (scale < 10) {
+ scale = 10;
+ }
+
+ if (scale == oldscale) {
+ return 0;
+ }
+
+ mutex_enter(&sc->sc_lock);
+ sc->sc_scale = scale;
+ amlogic_genfb_scaler_config(sc);
+ mutex_exit(&sc->sc_lock);
+
+ return 0;
}
static int
Index: src/sys/arch/arm/amlogic/amlogic_vpureg.h
diff -u src/sys/arch/arm/amlogic/amlogic_vpureg.h:1.1 src/sys/arch/arm/amlogic/amlogic_vpureg.h:1.2
--- src/sys/arch/arm/amlogic/amlogic_vpureg.h:1.1 Sat Mar 21 01:17:00 2015
+++ src/sys/arch/arm/amlogic/amlogic_vpureg.h Sun Mar 22 13:53:33 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: amlogic_vpureg.h,v 1.1 2015/03/21 01:17:00 jmcneill Exp $ */
+/* $NetBSD: amlogic_vpureg.h,v 1.2 2015/03/22 13:53:33 jmcneill Exp $ */
/*-
* Copyright (c) 2015 Jared D. McNeill <[email protected]>
@@ -38,6 +38,17 @@
#define VIU_OSD2_BLK0_CFG_W3_REG VPU_REG(0x1a3e)
#define VIU_OSD2_BLK0_CFG_W4_REG VPU_REG(0x1a64)
#define VPP_MISC_REG VPU_REG(0x1d26)
+#define VPP_OSD_VSC_PHASE_STEP_REG VPU_REG(0x1dc0)
+#define VPP_OSD_VSC_INI_PHASE_REG VPU_REG(0x1dc1)
+#define VPP_OSD_VSC_CTRL0_REG VPU_REG(0x1dc2)
+#define VPP_OSD_HSC_PHASE_STEP_REG VPU_REG(0x1dc3)
+#define VPP_OSD_HSC_INI_PHASE_REG VPU_REG(0x1dc4)
+#define VPP_OSD_HSC_CTRL0_REG VPU_REG(0x1dc5)
+#define VPP_OSD_SC_DUMMY_DATA_REG VPU_REG(0x1dc7)
+#define VPP_OSD_SC_CTRL0_REG VPU_REG(0x1dc8)
+#define VPP_OSD_SCI_WH_M1_REG VPU_REG(0x1dc9)
+#define VPP_OSD_SCO_H_REG VPU_REG(0x1dca)
+#define VPP_OSD_SCO_V_REG VPU_REG(0x1dcb)
#define VIU_OSD_CTRL_STAT_ENABLE __BIT(21)
#define VIU_OSD_CTRL_STAT_BLK3_ENABLE __BIT(3)
@@ -70,4 +81,43 @@
#define VPP_MISC_POSTBLEND __BIT(7)
+#define VPP_OSD_VSC_PHASE_STEP_FORMAT __BITS(27,0)
+
+#define VPP_OSD_VSC_INI_PHASE_0 __BITS(31,16)
+#define VPP_OSD_VSC_INI_PHASE_1 __BITS(15,0)
+
+#define VPP_OSD_VSC_CTRL0_VSCALE_EN __BIT(24)
+#define VPP_OSC_VSC_CTRL0_INTERLACE __BIT(23)
+#define VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0 __BITS(17,16)
+#define VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0 __BITS(14,11)
+#define VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0 __BITS(9,8)
+#define VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0 __BITS(6,3)
+#define VPP_OSD_VSC_CTRL0_BANK_LENGTH __BITS(2,0)
+
+#define VPP_OSD_HSC_PHASE_STEP_FORMAT __BITS(27,0)
+
+#define VPP_OSD_HSC_INI_PHASE_0 __BITS(31,16)
+#define VPP_OSD_HSC_INI_PHASE_1 __BITS(15,0)
+
+#define VPP_OSD_HSC_CTRL0_HSCALE_EN __BIT(22)
+#define VPP_OSD_HSC_CTRL0_RPT_P0_NUM0 __BITS(9,8)
+#define VPP_OSD_HSC_CTRL0_INI_RCV_NUM0 __BITS(6,3)
+#define VPP_OSD_HSC_CTRL0_BANK_LENGTH __BITS(2,0)
+
+#define VPP_OSD_SC_CTRL0_OSC_SC_DIN_OSD1_ALPHA_MODE __BIT(14)
+#define VPP_OSD_SC_CTRL0_OSC_SC_DIN_OSD2_ALPHA_MODE __BIT(13)
+#define VPP_OSD_SC_CTRL0_OSC_SC_ALPHA_MODE __BIT(12)
+#define VPP_OSD_SC_CTRL0_DEFAULT_ALPHA __BITS(11,4)
+#define VPP_OSD_SC_CTRL0_OSD_SC_PATH_EN __BIT(3)
+#define VPP_OSD_SC_CTRL0_OSD_SC_SEL __BITS(1,0)
+
+#define VPP_OSD_SCI_WH_M1_WIDTH __BITS(28,16)
+#define VPP_OSD_SCI_WH_M1_HEIGHT __BITS(12,0)
+
+#define VPP_OSD_SCO_H_START __BITS(28,16)
+#define VPP_OSD_SCO_H_END __BITS(12,0)
+
+#define VPP_OSD_SCO_V_START __BITS(28,16)
+#define VPP_OSD_SCO_V_END __BITS(12,0)
+
#endif /* _ARM_AMLOGIC_VPUREG_H */
Index: src/sys/arch/evbarm/amlogic/amlogic_machdep.c
diff -u src/sys/arch/evbarm/amlogic/amlogic_machdep.c:1.17 src/sys/arch/evbarm/amlogic/amlogic_machdep.c:1.18
--- src/sys/arch/evbarm/amlogic/amlogic_machdep.c:1.17 Sat Mar 21 01:17:00 2015
+++ src/sys/arch/evbarm/amlogic/amlogic_machdep.c Sun Mar 22 13:53:33 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: amlogic_machdep.c,v 1.17 2015/03/21 01:17:00 jmcneill Exp $ */
+/* $NetBSD: amlogic_machdep.c,v 1.18 2015/03/22 13:53:33 jmcneill Exp $ */
/*
* Machine dependent functions for kernel setup for TI OSK5912 board.
@@ -125,7 +125,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amlogic_machdep.c,v 1.17 2015/03/21 01:17:00 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amlogic_machdep.c,v 1.18 2015/03/22 13:53:33 jmcneill Exp $");
#include "opt_machdep.h"
#include "opt_ddb.h"
@@ -545,6 +545,7 @@ amlogic_device_register(device_t self, v
#if NGENFB > 0
if (device_is_a(self, "genfb")) {
char *ptr;
+ int scale;
amlogic_genfb_set_console_dev(self);
#ifdef DDB
db_trap_callback = amlogic_genfb_ddb_trap_callback;
@@ -558,6 +559,10 @@ amlogic_device_register(device_t self, v
} else {
prop_dictionary_set_bool(dict, "is_console", false);
}
+ if (get_bootconf_option(boot_args, "fb.scale",
+ BOOTOPT_TYPE_INT, &scale) && scale > 0) {
+ prop_dictionary_set_uint32(dict, "scale", scale);
+ }
}
#endif
}