Advertisement
jtl999

nouveau_backlight.c

Aug 25th, 2015
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.12 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2009 Red Hat <mjg@redhat.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining
  5.  * a copy of this software and associated documentation files (the
  6.  * "Software"), to deal in the Software without restriction, including
  7.  * without limitation the rights to use, copy, modify, merge, publish,
  8.  * distribute, sublicense, and/or sell copies of the Software, and to
  9.  * permit persons to whom the Software is furnished to do so, subject to
  10.  * the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the
  13.  * next paragraph) shall be included in all copies or substantial
  14.  * portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  20.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  */
  25.  
  26. /*
  27.  * Authors:
  28.  *  Matthew Garrett <mjg@redhat.com>
  29.  *
  30.  * Register locations derived from NVClock by Roderick Colenbrander
  31.  */
  32.  
  33. #include <linux/backlight.h>
  34.  
  35. #include "nouveau_drm.h"
  36. #include "nouveau_reg.h"
  37. #include "nouveau_encoder.h"
  38.  
  39. static int
  40. nv40_get_intensity(struct backlight_device *bd)
  41. {
  42.     struct nouveau_drm *drm = bl_get_data(bd);
  43.     struct nvif_device *device = &drm->device;
  44.     int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
  45.                    NV40_PMC_BACKLIGHT_MASK) >> 16;
  46.  
  47.     return val;
  48. }
  49.  
  50. static int
  51. nv40_set_intensity(struct backlight_device *bd)
  52. {
  53.     struct nouveau_drm *drm = bl_get_data(bd);
  54.     struct nvif_device *device = &drm->device;
  55.     int val = bd->props.brightness;
  56.     int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
  57.  
  58.     nvif_wr32(device, NV40_PMC_BACKLIGHT,
  59.          (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
  60.  
  61.     return 0;
  62. }
  63.  
  64. static const struct backlight_ops nv40_bl_ops = {
  65.     .options = BL_CORE_SUSPENDRESUME,
  66.     .get_brightness = nv40_get_intensity,
  67.     .update_status = nv40_set_intensity,
  68. };
  69.  
  70. static int
  71. nv40_backlight_init(struct drm_connector *connector)
  72. {
  73.     struct nouveau_drm *drm = nouveau_drm(connector->dev);
  74.     struct nvif_device *device = &drm->device;
  75.     struct backlight_properties props;
  76.     struct backlight_device *bd;
  77.  
  78.     if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
  79.         return 0;
  80.  
  81.     memset(&props, 0, sizeof(struct backlight_properties));
  82.     props.type = BACKLIGHT_RAW;
  83.     props.max_brightness = 31;
  84.     bd = backlight_device_register("nv_backlight", connector->kdev, drm,
  85.                        &nv40_bl_ops, &props);
  86.     if (IS_ERR(bd))
  87.         return PTR_ERR(bd);
  88.     drm->backlight = bd;
  89.     bd->props.brightness = nv40_get_intensity(bd);
  90.     backlight_update_status(bd);
  91.  
  92.     return 0;
  93. }
  94.  
  95. static int
  96. nv50_get_intensity(struct backlight_device *bd)
  97. {
  98.     struct nouveau_encoder *nv_encoder = bl_get_data(bd);
  99.     struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
  100.     struct nvif_device *device = &drm->device;
  101.     int or = nv_encoder->or;
  102.     u32 div = 1025;
  103.     u32 val;
  104.  
  105.     val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
  106.     val &= NV50_PDISP_SOR_PWM_CTL_VAL;
  107.     return ((val * 100) + (div / 2)) / div;
  108. }
  109.  
  110. static int
  111. nv50_set_intensity(struct backlight_device *bd)
  112. {
  113.     struct nouveau_encoder *nv_encoder = bl_get_data(bd);
  114.     struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
  115.     struct nvif_device *device = &drm->device;
  116.     int or = nv_encoder->or;
  117.     u32 div = 1025;
  118.     u32 val = (bd->props.brightness * div) / 100;
  119.  
  120.     nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
  121.             NV50_PDISP_SOR_PWM_CTL_NEW | val);
  122.     return 0;
  123. }
  124.  
  125. static const struct backlight_ops nv50_bl_ops = {
  126.     .options = BL_CORE_SUSPENDRESUME,
  127.     .get_brightness = nv50_get_intensity,
  128.     .update_status = nv50_set_intensity,
  129. };
  130.  
  131. static int
  132. nva3_get_intensity(struct backlight_device *bd)
  133. {
  134.     struct nouveau_encoder *nv_encoder = bl_get_data(bd);
  135.     struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
  136.     struct nvif_device *device = &drm->device;
  137.     int or = nv_encoder->or;
  138.     u32 div, val;
  139.  
  140.     div  = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
  141.     val  = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
  142.     val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
  143.     if (div && div >= val)
  144.         return ((val * 100) + (div / 2)) / div;
  145.  
  146.     return 100;
  147. }
  148.  
  149. static int
  150. nva3_set_intensity(struct backlight_device *bd)
  151. {
  152.     struct nouveau_encoder *nv_encoder = bl_get_data(bd);
  153.     struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
  154.     struct nvif_device *device = &drm->device;
  155.     int or = nv_encoder->or;
  156.     u32 div, val;
  157.  
  158.     div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
  159.     val = (bd->props.brightness * div) / 100;
  160.     if (div) {
  161.         nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
  162.                 NV50_PDISP_SOR_PWM_CTL_NEW |
  163.                 NVA3_PDISP_SOR_PWM_CTL_UNK);
  164.         return 0;
  165.     }
  166.  
  167.     return -EINVAL;
  168. }
  169.  
  170. static const struct backlight_ops nva3_bl_ops = {
  171.     .options = BL_CORE_SUSPENDRESUME,
  172.     .get_brightness = nva3_get_intensity,
  173.     .update_status = nva3_set_intensity,
  174. };
  175.  
  176. static int
  177. nv50_backlight_init(struct drm_connector *connector)
  178. {
  179.     struct nouveau_drm *drm = nouveau_drm(connector->dev);
  180.     struct nvif_device *device = &drm->device;
  181.     struct nouveau_encoder *nv_encoder;
  182.     struct backlight_properties props;
  183.     struct backlight_device *bd;
  184.     const struct backlight_ops *ops;
  185.  
  186.     nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
  187.     if (!nv_encoder) {
  188.         nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
  189.         if (!nv_encoder)
  190.             return -ENODEV;
  191.     }
  192.  
  193.     if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
  194.         return 0;
  195.  
  196.     if (device->info.chipset <= 0xa0 ||
  197.         device->info.chipset == 0xaa ||
  198.         device->info.chipset == 0xac)
  199.         ops = &nv50_bl_ops;
  200.     else
  201.         ops = &nva3_bl_ops;
  202.  
  203.     memset(&props, 0, sizeof(struct backlight_properties));
  204.     props.type = BACKLIGHT_RAW;
  205.     props.max_brightness = 100;
  206.     bd = backlight_device_register("nv_backlight", connector->kdev,
  207.                        nv_encoder, ops, &props);
  208.     if (IS_ERR(bd))
  209.         return PTR_ERR(bd);
  210.  
  211.     drm->backlight = bd;
  212.     bd->props.brightness = bd->ops->get_brightness(bd);
  213.     backlight_update_status(bd);
  214.     return 0;
  215. }
  216.  
  217. int
  218. nouveau_backlight_init(struct drm_device *dev)
  219. {
  220.     struct nouveau_drm *drm = nouveau_drm(dev);
  221.     struct nvif_device *device = &drm->device;
  222.     struct drm_connector *connector;
  223.  
  224.     list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  225.         if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
  226.             connector->connector_type != DRM_MODE_CONNECTOR_eDP)
  227.             continue;
  228.  
  229.         switch (device->info.family) {
  230.         case NV_DEVICE_INFO_V0_CURIE:
  231.             return nv40_backlight_init(connector);
  232.         case NV_DEVICE_INFO_V0_TESLA:
  233.         case NV_DEVICE_INFO_V0_FERMI:
  234.         case NV_DEVICE_INFO_V0_KEPLER:
  235.             return nv50_backlight_init(connector);
  236.         default:
  237.             break;
  238.         }
  239.     }
  240.  
  241.  
  242.     return 0;
  243. }
  244.  
  245. void
  246. nouveau_backlight_exit(struct drm_device *dev)
  247. {
  248.     struct nouveau_drm *drm = nouveau_drm(dev);
  249.  
  250.     if (drm->backlight) {
  251.         backlight_device_unregister(drm->backlight);
  252.         drm->backlight = NULL;
  253.     }
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement