diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/rockchip_sdhci.c | 76 | ||||
-rw-r--r-- | drivers/phy/cadence/phy-cadence-sierra.c | 59 | ||||
-rw-r--r-- | drivers/video/video-uclass.c | 7 | ||||
-rw-r--r-- | drivers/video/video_bmp.c | 70 |
4 files changed, 148 insertions, 64 deletions
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 278473899c7..b91df05de4f 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -90,9 +90,33 @@ struct rockchip_sdhc { }; struct sdhci_data { - int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock); int (*emmc_phy_init)(struct udevice *dev); int (*get_phy)(struct udevice *dev); + + /** + * set_control_reg() - Set SDHCI control registers + * + * This is the set_control_reg() SDHCI operation that should be + * used for the hardware this driver data is associated with. + * Normally, this is used to set up control registers for + * voltage level and UHS speed mode. + * + * @host: SDHCI host structure + */ + void (*set_control_reg)(struct sdhci_host *host); + + /** + * set_ios_post() - Host specific hook after set_ios() calls + * + * This is the set_ios_post() SDHCI operation that should be + * used for the hardware this driver data is associated with. + * Normally, this is a hook that is called after sdhci_set_ios() + * that does any necessary host-specific configuration. + * + * @host: SDHCI host structure + * Return: 0 if successful, -ve on error + */ + int (*set_ios_post)(struct sdhci_host *host); }; static int rk3399_emmc_phy_init(struct udevice *dev) @@ -182,15 +206,28 @@ static int rk3399_emmc_get_phy(struct udevice *dev) return 0; } -static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock) +static void rk3399_sdhci_set_control_reg(struct sdhci_host *host) { struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct mmc *mmc = host->mmc; + uint clock = mmc->tran_speed; int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ; if (cycle_phy) rk3399_emmc_phy_power_off(priv->phy); - sdhci_set_clock(host->mmc, clock); + sdhci_set_control_reg(host); +}; + +static int rk3399_sdhci_set_ios_post(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct mmc *mmc = host->mmc; + uint clock = mmc->tran_speed; + int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ; + + if (!clock) + clock = mmc->clock; if (cycle_phy) rk3399_emmc_phy_power_on(priv->phy, clock); @@ -269,10 +306,8 @@ static int rk3568_emmc_get_phy(struct udevice *dev) return 0; } -static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) +static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { - struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); - struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); struct mmc *mmc = host->mmc; uint clock = mmc->tran_speed; u32 reg; @@ -280,8 +315,7 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) if (!clock) clock = mmc->clock; - if (data->emmc_set_clock) - data->emmc_set_clock(host, clock); + rk3568_sdhci_emmc_set_clock(host, clock); if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) { reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); @@ -295,6 +329,26 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) return 0; } +static void rockchip_sdhci_set_control_reg(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); + + if (data->set_control_reg) + data->set_control_reg(host); +} + +static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); + + if (data->set_ios_post) + return data->set_ios_post(host); + + return 0; +} + static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) { struct sdhci_host *host = dev_get_priv(mmc->dev); @@ -358,6 +412,7 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) static struct sdhci_ops rockchip_sdhci_ops = { .set_ios_post = rockchip_sdhci_set_ios_post, .platform_execute_tuning = &rockchip_sdhci_execute_tuning, + .set_control_reg = rockchip_sdhci_set_control_reg, }; static int rockchip_sdhci_probe(struct udevice *dev) @@ -436,15 +491,16 @@ static int rockchip_sdhci_bind(struct udevice *dev) } static const struct sdhci_data rk3399_data = { - .emmc_set_clock = rk3399_sdhci_emmc_set_clock, .get_phy = rk3399_emmc_get_phy, .emmc_phy_init = rk3399_emmc_phy_init, + .set_control_reg = rk3399_sdhci_set_control_reg, + .set_ios_post = rk3399_sdhci_set_ios_post, }; static const struct sdhci_data rk3568_data = { - .emmc_set_clock = rk3568_sdhci_emmc_set_clock, .get_phy = rk3568_emmc_get_phy, .emmc_phy_init = rk3568_emmc_phy_init, + .set_ios_post = rk3568_sdhci_set_ios_post, }; static const struct udevice_id sdhci_ids[] = { diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index d95d4b432a9..fc5044fd5d3 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -358,26 +358,10 @@ static inline int cdns_reset_deassert(struct reset_control *rst) return 0; } -static inline struct cdns_sierra_inst *phy_get_drvdata(struct phy *phy) +static int cdns_sierra_link_init(struct phy *gphy) { - struct cdns_sierra_phy *sp = dev_get_priv(phy->dev); - int index; - - if (phy->id >= SIERRA_MAX_LANES) - return NULL; - - for (index = 0; index < sp->nsubnodes; index++) { - if (phy->id == sp->phys[index]->mlane) - return sp->phys[index]; - } - - return NULL; -} - -static int cdns_sierra_phy_init(struct phy *gphy) -{ - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); - struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev->parent); struct cdns_sierra_data *init_data = phy->init_data; struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals; enum cdns_sierra_phy_type phy_type = ins->phy_type; @@ -443,10 +427,11 @@ static int cdns_sierra_phy_init(struct phy *gphy) return 0; } -static int cdns_sierra_phy_on(struct phy *gphy) +static int cdns_sierra_link_on(struct phy *gphy) { - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); - struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent); + struct udevice *dev = gphy->dev; u32 val; int ret; @@ -503,16 +488,16 @@ static int cdns_sierra_phy_on(struct phy *gphy) return ret; } -static int cdns_sierra_phy_off(struct phy *gphy) +static int cdns_sierra_link_off(struct phy *gphy) { - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); return reset_assert_bulk(ins->lnk_rst); } -static int cdns_sierra_phy_reset(struct phy *gphy) +static int cdns_sierra_link_reset(struct phy *gphy) { - struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent); reset_control_assert(sp->phy_rst); reset_control_deassert(sp->phy_rst); @@ -520,10 +505,10 @@ static int cdns_sierra_phy_reset(struct phy *gphy) }; static const struct phy_ops ops = { - .init = cdns_sierra_phy_init, - .power_on = cdns_sierra_phy_on, - .power_off = cdns_sierra_phy_off, - .reset = cdns_sierra_phy_reset, + .init = cdns_sierra_link_init, + .power_on = cdns_sierra_link_on, + .power_off = cdns_sierra_link_off, + .reset = cdns_sierra_link_reset, }; struct cdns_sierra_pll_mux_sel { @@ -580,7 +565,7 @@ static const struct clk_ops cdns_sierra_pll_mux_ops = { .set_parent = cdns_sierra_pll_mux_set_parent, }; -int cdns_sierra_pll_mux_probe(struct udevice *dev) +static int cdns_sierra_pll_mux_probe(struct udevice *dev) { struct cdns_sierra_pll_mux *priv = dev_get_priv(dev); struct cdns_sierra_phy *sp = dev_get_priv(dev->parent); @@ -1012,9 +997,8 @@ static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp, return 0; } -static int cdns_sierra_bind_link_nodes(struct cdns_sierra_phy *sp) +static int cdns_sierra_phy_bind(struct udevice *dev) { - struct udevice *dev = sp->dev; struct driver *link_drv; ofnode child; int rc; @@ -1079,6 +1063,7 @@ U_BOOT_DRIVER(sierra_phy_link) = { .name = "sierra_phy_link", .id = UCLASS_PHY, .probe = cdns_sierra_link_probe, + .ops = &ops, .priv_auto = sizeof(struct cdns_sierra_inst), }; @@ -1141,10 +1126,6 @@ static int cdns_sierra_phy_probe(struct udevice *dev) } sp->autoconf = dev_read_bool(dev, "cdns,autoconf"); - /* Binding link nodes as children to serdes */ - ret = cdns_sierra_bind_link_nodes(sp); - if (ret) - goto clk_disable; dev_info(dev, "sierra probed\n"); return 0; @@ -1971,10 +1952,10 @@ static const struct udevice_id cdns_sierra_id_table[] = { U_BOOT_DRIVER(sierra_phy_provider) = { .name = "cdns,sierra", - .id = UCLASS_PHY, + .id = UCLASS_MISC, .of_match = cdns_sierra_id_table, .probe = cdns_sierra_phy_probe, .remove = cdns_sierra_phy_remove, - .ops = &ops, + .bind = cdns_sierra_phy_bind, .priv_auto = sizeof(struct cdns_sierra_phy), }; diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 7d499bcec51..88797d4a21c 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -33,7 +33,8 @@ * information represents the requires size and alignment of the frame buffer * for the device. The values can be an over-estimate but cannot be too * small. The actual values will be suppled (in the same manner) by the bind() - * method after relocation. + * method after relocation. Additionally driver can allocate frame buffer + * itself by setting plat->base. * * This information is then picked up by video_reserve() which works out how * much memory is needed for all devices. This is allocated between @@ -78,6 +79,10 @@ static ulong alloc_fb(struct udevice *dev, ulong *addrp) if (!plat->size) return 0; + /* Allow drivers to allocate the frame buffer themselves */ + if (plat->base) + return 0; + align = plat->align ? plat->align : 1 << 20; base = *addrp - plat->size; base &= ~(align - 1); diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index c8c3fd3549d..4d2d961696a 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -31,6 +31,18 @@ static uint get_bmp_col_16bpp(struct bmp_color_table_entry cte) } /** + * get_bmp_col_x2r10g10b10() - Convert a colour-table entry into a x2r10g10b10 pixel value + * + * Return: value to write to the x2r10g10b10 frame buffer for this palette entry + */ +static u32 get_bmp_col_x2r10g10b10(struct bmp_color_table_entry *cte) +{ + return ((cte->red << 22U) | + (cte->green << 12U) | + (cte->blue << 2U)); +} + +/** * write_pix8() - Write a pixel from a BMP image into the framebuffer * * This handles frame buffers with 8, 16, 24 or 32 bits per pixel @@ -42,8 +54,8 @@ static uint get_bmp_col_16bpp(struct bmp_color_table_entry cte) * which is either written directly (bpix == 8) or used to look up the * palette to get a colour to write */ -static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette, - u8 *bmap) +static void write_pix8(u8 *fb, uint bpix, enum video_format eformat, + struct bmp_color_table_entry *palette, u8 *bmap) { if (bpix == 8) { *fb++ = *bmap; @@ -57,6 +69,8 @@ static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette, *fb++ = cte->red; *fb++ = cte->green; *fb++ = cte->blue; + } else if (eformat == VIDEO_X2R10G10B10) { + *(u32 *)fb = get_bmp_col_x2r10g10b10(cte); } else { *fb++ = cte->blue; *fb++ = cte->green; @@ -66,28 +80,29 @@ static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette, } } -static void draw_unencoded_bitmap(u8 **fbp, uint bpix, uchar *bmap, +static void draw_unencoded_bitmap(u8 **fbp, uint bpix, + enum video_format eformat, uchar *bmap, struct bmp_color_table_entry *palette, int cnt) { u8 *fb = *fbp; while (cnt > 0) { - write_pix8(fb, bpix, palette, bmap++); + write_pix8(fb, bpix, eformat, palette, bmap++); fb += bpix / 8; cnt--; } *fbp = fb; } -static void draw_encoded_bitmap(u8 **fbp, uint bpix, +static void draw_encoded_bitmap(u8 **fbp, uint bpix, enum video_format eformat, struct bmp_color_table_entry *palette, u8 *bmap, int cnt) { u8 *fb = *fbp; while (cnt > 0) { - write_pix8(fb, bpix, palette, bmap); + write_pix8(fb, bpix, eformat, palette, bmap); fb += bpix / 8; cnt--; } @@ -106,6 +121,7 @@ static void video_display_rle8_bitmap(struct udevice *dev, int x, y; int decode = 1; uint bytes_per_pixel = bpix / 8; + enum video_format eformat = priv->format; debug("%s\n", __func__); bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); @@ -148,7 +164,7 @@ static void video_display_rle8_bitmap(struct udevice *dev, else cnt = runlen; draw_unencoded_bitmap( - &fb, bpix, + &fb, bpix, eformat, bmap, palette, cnt); } x += runlen; @@ -173,8 +189,9 @@ static void video_display_rle8_bitmap(struct udevice *dev, cnt = width - x; else cnt = runlen; - draw_encoded_bitmap(&fb, bpix, palette, - &bmap[1], cnt); + draw_encoded_bitmap(&fb, bpix, eformat, + palette, &bmap[1], + cnt); } x += runlen; } @@ -224,6 +241,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, unsigned long width, height, byte_width; unsigned long pwidth = priv->xsize; unsigned colours, bpix, bmp_bpix; + enum video_format eformat; struct bmp_color_table_entry *palette; int hdr_size; int ret; @@ -245,6 +263,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, colours = 1 << bmp_bpix; bpix = VNBITS(priv->bpix); + eformat = priv->format; if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) { printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", @@ -312,7 +331,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, for (i = 0; i < height; ++i) { WATCHDOG_RESET(); for (j = 0; j < width; j++) { - write_pix8(fb, bpix, palette, bmap); + write_pix8(fb, bpix, eformat, palette, bmap); bmap++; fb += bpix / 8; } @@ -345,6 +364,16 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, (bmap[0] >> 3); bmap += 3; fb += 2; + } else if (eformat == VIDEO_X2R10G10B10) { + u32 pix; + + pix = *bmap++ << 2U; + pix |= *bmap++ << 12U; + pix |= *bmap++ << 22U; + *fb++ = pix & 0xff; + *fb++ = (pix >> 8) & 0xff; + *fb++ = (pix >> 16) & 0xff; + *fb++ = pix >> 24; } else { *fb++ = *bmap++; *fb++ = *bmap++; @@ -361,10 +390,23 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, if (IS_ENABLED(CONFIG_BMP_32BPP)) { for (i = 0; i < height; ++i) { for (j = 0; j < width; j++) { - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = *bmap++; - *fb++ = *bmap++; + if (eformat == VIDEO_X2R10G10B10) { + u32 pix; + + pix = *bmap++ << 2U; + pix |= *bmap++ << 12U; + pix |= *bmap++ << 22U; + pix |= (*bmap++ >> 6) << 30U; + *fb++ = pix & 0xff; + *fb++ = (pix >> 8) & 0xff; + *fb++ = (pix >> 16) & 0xff; + *fb++ = pix >> 24; + } else { + *fb++ = *bmap++; + *fb++ = *bmap++; + *fb++ = *bmap++; + *fb++ = *bmap++; + } } fb -= priv->line_length + width * (bpix / 8); } |