1 /* 2 * Copyright (c) 2013 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <errno.h> 10 #include <fdtdec.h> 11 #include <malloc.h> 12 #include <dm-demo.h> 13 #include <asm/io.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 /* Shape size */ 18 #define WIDTH 8 19 #define HEIGHT 6 20 21 struct shape_data { 22 int num_chars; /* Number of non-space characters output so far */ 23 }; 24 25 /* Crazy little function to draw shapes on the console */ 26 static int shape_hello(struct device *dev, int ch) 27 { 28 const struct dm_demo_pdata *pdata = dev_get_platdata(dev); 29 struct shape_data *data = dev_get_priv(dev); 30 static const struct shape { 31 int start; 32 int end; 33 int dstart; 34 int dend; 35 } shapes[3] = { 36 { 0, 1, 0, 1 }, 37 { 0, WIDTH, 0, 0 }, 38 { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1}, 39 }; 40 struct shape shape; 41 unsigned int index; 42 int line, pos, inside; 43 const char *colour = pdata->colour; 44 int first = 0; 45 46 if (!ch) 47 ch = pdata->default_char; 48 if (!ch) 49 ch = '@'; 50 51 index = (pdata->sides / 2) - 1; 52 if (index >= ARRAY_SIZE(shapes)) 53 return -EIO; 54 shape = shapes[index]; 55 56 for (line = 0; line < HEIGHT; line++) { 57 first = 1; 58 for (pos = 0; pos < WIDTH; pos++) { 59 inside = pos >= shape.start && pos < shape.end; 60 if (inside) { 61 putc(first ? *colour++ : ch); 62 data->num_chars++; 63 first = 0; 64 if (!*colour) 65 colour = pdata->colour; 66 } else { 67 putc(' '); 68 } 69 } 70 putc('\n'); 71 shape.start += shape.dstart; 72 shape.end += shape.dend; 73 if (shape.start < 0) { 74 shape.dstart = -shape.dstart; 75 shape.dend = -shape.dend; 76 shape.start += shape.dstart; 77 shape.end += shape.dend; 78 } 79 } 80 81 return 0; 82 } 83 84 static int shape_status(struct device *dev, int *status) 85 { 86 struct shape_data *data = dev_get_priv(dev); 87 88 *status = data->num_chars; 89 return 0; 90 } 91 92 static const struct demo_ops shape_ops = { 93 .hello = shape_hello, 94 .status = shape_status, 95 }; 96 97 static int shape_ofdata_to_platdata(struct device *dev) 98 { 99 struct dm_demo_pdata *pdata = dev_get_platdata(dev); 100 int ret; 101 102 /* Parse the data that is common with all demo devices */ 103 ret = demo_parse_dt(dev); 104 if (ret) 105 return ret; 106 107 /* Parse the data that only we need */ 108 pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 109 "character", '@'); 110 111 return 0; 112 } 113 114 static const struct device_id demo_shape_id[] = { 115 { "demo-shape", 0 }, 116 { }, 117 }; 118 119 U_BOOT_DRIVER(demo_shape_drv) = { 120 .name = "demo_shape_drv", 121 .of_match = demo_shape_id, 122 .id = UCLASS_DEMO, 123 .ofdata_to_platdata = shape_ofdata_to_platdata, 124 .ops = &shape_ops, 125 .priv_auto_alloc_size = sizeof(struct shape_data), 126 .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata), 127 }; 128