demo-shape.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2013 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <fdtdec.h>
  9. #include <log.h>
  10. #include <malloc.h>
  11. #include <dm-demo.h>
  12. #include <asm/io.h>
  13. #include <asm/gpio.h>
  14. DECLARE_GLOBAL_DATA_PTR;
  15. /* Shape size */
  16. #define WIDTH 8
  17. #define HEIGHT 6
  18. struct shape_data {
  19. int num_chars; /* Number of non-space characters output so far */
  20. struct gpio_desc gpio_desc[8];
  21. int gpio_count;
  22. };
  23. /* Crazy little function to draw shapes on the console */
  24. static int shape_hello(struct udevice *dev, int ch)
  25. {
  26. const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
  27. struct shape_data *data = dev_get_priv(dev);
  28. static const struct shape {
  29. int start;
  30. int end;
  31. int dstart;
  32. int dend;
  33. } shapes[3] = {
  34. { 0, 1, 0, 1 },
  35. { 0, WIDTH, 0, 0 },
  36. { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
  37. };
  38. struct shape shape;
  39. unsigned int index;
  40. int line, pos, inside;
  41. const char *colour = pdata->colour;
  42. int first = 0;
  43. if (!ch)
  44. ch = pdata->default_char;
  45. if (!ch)
  46. ch = '@';
  47. index = (pdata->sides / 2) - 1;
  48. if (index >= ARRAY_SIZE(shapes))
  49. return -EIO;
  50. shape = shapes[index];
  51. for (line = 0; line < HEIGHT; line++) {
  52. first = 1;
  53. for (pos = 0; pos < WIDTH; pos++) {
  54. inside = pos >= shape.start && pos < shape.end;
  55. if (inside) {
  56. putc(first ? *colour++ : ch);
  57. data->num_chars++;
  58. first = 0;
  59. if (!*colour)
  60. colour = pdata->colour;
  61. } else {
  62. putc(' ');
  63. }
  64. }
  65. putc('\n');
  66. shape.start += shape.dstart;
  67. shape.end += shape.dend;
  68. if (shape.start < 0) {
  69. shape.dstart = -shape.dstart;
  70. shape.dend = -shape.dend;
  71. shape.start += shape.dstart;
  72. shape.end += shape.dend;
  73. }
  74. }
  75. return 0;
  76. }
  77. static int shape_status(struct udevice *dev, int *status)
  78. {
  79. struct shape_data *data = dev_get_priv(dev);
  80. *status = data->num_chars;
  81. return 0;
  82. }
  83. static int set_light(struct udevice *dev, int light)
  84. {
  85. struct shape_data *priv = dev_get_priv(dev);
  86. struct gpio_desc *desc;
  87. int ret;
  88. int i;
  89. desc = priv->gpio_desc;
  90. for (i = 0; i < priv->gpio_count; i++, desc++) {
  91. uint mask = 1 << i;
  92. ret = dm_gpio_set_value(desc, light & mask);
  93. if (ret < 0)
  94. return ret;
  95. }
  96. return 0;
  97. }
  98. static int get_light(struct udevice *dev)
  99. {
  100. struct shape_data *priv = dev_get_priv(dev);
  101. struct gpio_desc *desc;
  102. uint value = 0;
  103. int ret;
  104. int i;
  105. desc = priv->gpio_desc;
  106. for (i = 0; i < priv->gpio_count; i++, desc++) {
  107. uint mask = 1 << i;
  108. ret = dm_gpio_get_value(desc);
  109. if (ret < 0)
  110. return ret;
  111. if (ret)
  112. value |= mask;
  113. }
  114. return value;
  115. }
  116. static const struct demo_ops shape_ops = {
  117. .hello = shape_hello,
  118. .status = shape_status,
  119. .get_light = get_light,
  120. .set_light = set_light,
  121. };
  122. static int shape_ofdata_to_platdata(struct udevice *dev)
  123. {
  124. struct dm_demo_pdata *pdata = dev_get_platdata(dev);
  125. int ret;
  126. /* Parse the data that is common with all demo devices */
  127. ret = demo_parse_dt(dev);
  128. if (ret)
  129. return ret;
  130. /* Parse the data that only we need */
  131. pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
  132. "character", '@');
  133. return 0;
  134. }
  135. static int dm_shape_probe(struct udevice *dev)
  136. {
  137. struct shape_data *priv = dev_get_priv(dev);
  138. int ret;
  139. ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
  140. ARRAY_SIZE(priv->gpio_desc),
  141. GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
  142. if (ret < 0)
  143. return ret;
  144. priv->gpio_count = ret;
  145. debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
  146. return 0;
  147. }
  148. static int dm_shape_remove(struct udevice *dev)
  149. {
  150. struct shape_data *priv = dev_get_priv(dev);
  151. return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
  152. }
  153. static const struct udevice_id demo_shape_id[] = {
  154. { "demo-shape", 0 },
  155. { },
  156. };
  157. U_BOOT_DRIVER(demo_shape_drv) = {
  158. .name = "demo_shape_drv",
  159. .of_match = demo_shape_id,
  160. .id = UCLASS_DEMO,
  161. .ofdata_to_platdata = shape_ofdata_to_platdata,
  162. .ops = &shape_ops,
  163. .probe = dm_shape_probe,
  164. .remove = dm_shape_remove,
  165. .priv_auto_alloc_size = sizeof(struct shape_data),
  166. .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
  167. };