demo-shape.c 4.0 KB

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